CS(Computer Science)지식/[C++] 디자인 패턴
방문자 패턴(Visitor Pattern)이해하기 : 쉽게 설명한 디자인 패턴(C++)
엔지니어 청년
2024. 1. 29. 21:52
방문자 패턴(Visitor Pattern)이란?
방문자 패턴은 객체 지향 디자인 패턴 중 하나로, 특정 연산을 객체의 구조에 대해 수행하도록 하는 패턴입니다. 이 패턴은 연산을 수행하려는 객체에서 분리하여 새로운 연산을 추가하거나 기존 연산을 변경하는 것을 쉽게 만들어줍니다. 이 패턴은 주로 복잡한 객체 구조에 대해 연산을 수행할 때 사용됩니다.
방문자 패턴은 다음 두 가지 주요 구성 요소로 이루어져 있습니다:
- Visitor: 방문자 인터페이스로, 방문할 객체의 클래스에 대한 방문 연산을 선언합니다.
- ConcreteVisitor: 방문자 인터페이스를 구현하고, 각 클래스에 대한 방문 연산을 정의합니다.
예시 코드
다음은 C++로 작성된 간단한 방문자 패턴의 예입니다:
#include <iostream>
class ConcreteElementA;
class ConcreteElementB;
class Visitor {
public:
virtual void visitConcreteElementA(ConcreteElementA* element) = 0;
virtual void visitConcreteElementB(ConcreteElementB* element) = 0;
};
class ConcreteVisitor1 : public Visitor {
public:
void visitConcreteElementA(ConcreteElementA* element) override {
std::cout << "ConcreteVisitor1: Visited ConcreteElementA\n";
}
void visitConcreteElementB(ConcreteElementB* element) override {
std::cout << "ConcreteVisitor1: Visited ConcreteElementB\n";
}
};
class ConcreteVisitor2 : public Visitor {
public:
void visitConcreteElementA(ConcreteElementA* element) override {
std::cout << "ConcreteVisitor2: Visited ConcreteElementA\n";
}
void visitConcreteElementB(ConcreteElementB* element) override {
std::cout << "ConcreteVisitor2: Visited ConcreteElementB\n";
}
};
class Element {
public:
virtual void accept(Visitor* visitor) = 0;
};
class ConcreteElementA : public Element {
public:
void accept(Visitor* visitor) override {
visitor->visitConcreteElementA(this);
}
};
class ConcreteElementB : public Element {
public:
void accept(Visitor* visitor) override {
visitor->visitConcreteElementB(this);
}
};
int main() {
ConcreteElementA elementA;
ConcreteElementB elementB;
ConcreteVisitor1 visitor1;
ConcreteVisitor2 visitor2;
elementA.accept(&visitor1);
elementB.accept(&visitor1);
elementA.accept(&visitor2);
elementB.accept(&visitor2);
}
위 코드에서 Visitor는 방문자 인터페이스로, 방문할 객체의 클래스에 대한 방문 연산을 선언합니다. ConcreteVisitor1과 ConcreteVisitor2는 Visitor 인터페이스를 구현하고, 각 클래스에 대한 방문 연산을 정의합니다. Element는 방문할 객체의 인터페이스로, 방문자를 받아들이는 연산을 선언합니다. ConcreteElementA와 ConcreteElementB는 Element 인터페이스를 구현하고, 방문자를 받아들이는 연산을 정의합니다.
클래스 다이어그램
+-----------------+
| Visitor |
+-----------------+
| visitConcreteElementA() |
| visitConcreteElementB() |
+-----------------+
^
|
+-----------------+ +-----------------+
| ConcreteVisitor1| | ConcreteVisitor2|
+-----------------+ +-----------------+
| visitConcreteElementA() | | visitConcreteElementA() |
| visitConcreteElementB() | | visitConcreteElementB() |
+-----------------+ +-----------------+
+-----------------+
| Element |
+-----------------+
| accept() |
+-----------------+
^
|
+-----------------+ +-----------------+
| ConcreteElementA| | ConcreteElementB|
+-----------------+ +-----------------+
| accept() | | accept() |
+-----------------+ +-----------------+
방문자 패턴은 객체 구조와 연산을 분리하여 코드의 유연성을 높이고, 새로운 연산을 쉽게 추가할 수 있게 해줍니다. 하지만 이 패턴을 사용하면 코드가 복잡해질 수 있으므로, 실제로 객체 구조에 대해 복잡한 연산을 수행해야 하는 경우에만 이 패턴을 사용하는 것이 좋습니다.