방문자 패턴(Visitor Pattern)은 객체와 기능을 분리할 수 있도록 하는 디자인 패턴이다.
구현
방문자 패턴은
- Visitor
- Concrete Visitor
- Element Interface
- Element
- Client
로 구성된다.
Visitor 객체는 Element 객체들을 순회하며 각 Element에 필요한 기능을 수행한다.
Visitor
Concrete Visitor의 인터페이스로 각 Concrete Visitor는 매개변수가 다르다.
// Visitor interface
class Visitor {
public:
virtual void visit(ConcreteElementA* element) = 0;
virtual void visit(ConcreteElementB* element) = 0;
};
Concrete Visitor
Concrete Element에 맞게 작성된 같은 행동의 여러 버전을 구현한다.
// Concrete visitor
class ConcreteVisitor : public Visitor {
public:
void visit(ConcreteElementA* element) override {
std::cout << "Visit ConcreteElementA" << std::endl;
}
void visit(ConcreteElementB* element) override {
std::cout << "Visit ConcreteElementB" << std::endl;
}
};
Element Interface
Visitor를 수락하는 메소드를 선언한다.
// Element interface
class Element {
public:
virtual void accept(Visitor* visitor) = 0;
};
Concrete Element
수락 메소드를 구현한다. 메소드가 호출되면 요소에 적당한 Visitor 메소드로 리다이렉트한다.
// Concrete element A
class ConcreteElementA : public Element {
public:
void accept(Visitor* visitor) override {
visitor->visit(this);
}
};
// Concrete element B
class ConcreteElementB : public Element {
public:
void accept(Visitor* visitor) override {
visitor->visit(this);
}
};
Client (예시)
visitor
는 elementA
, elementB
를 (accept
를 통해) 방문하고, (visit
을 통해) 방문을 처리한다.
int main() {
ConcreteElementA elementA;
ConcreteElementB elementB;
ConcreteVisitor visitor;
elementA.accept(&visitor);
elementB.accept(&visitor);
return 0;
}
장점
- 개방/폐쇄 원칙을 만족한다. 클래스를 변경하지 않고 클래스의 객체와 작동할 수 있는 새 기능을 추가할 수 있다.
- 단일 책임 원칙을 만족한다. 같은 행동의 여러 버전을 같은 클래스로 이동할 수 있다.
단점
- 클래스가 Element에 추가될 때마다 모든 Visitor를 업데이트해야 한다.
- Visitor가 Element의 Private Field나 메소드에 접근하기 위해 필요한 권한이 부족할 수 있다.
반응형