Visitor Pattern은 객체 지향 디자인 패턴 중 하나로, 객체를 탐색하고 객체의 각 요소에 대해 작업을 수행하는 방법을 제공합니다. 이 패턴은 객체의 구조와 작업을 분리하고, 새로운 작업을 추가하거나 객체 구조를 수정하지 않고도 작업을 수행할 수 있게 합니다.
패턴의 핵심 아이디어는 방문자(visitor)라는 개체를 사용하는 것입니다. 방문자는 객체 구조를 탐색하고 각 객체에 대해 특정 작업을 수행합니다. 이 때 객체는 방문자를 인자로 전달하고, 방문자는 객체의 메소드를 호출하여 작업을 수행합니다.
1. 예제 코드
Python 예제 코드를 통해 이해해보겠습니다.
class Element:
def accept(self, visitor):
pass
class ConcreteElementA(Element):
def accept(self, visitor):
visitor.visit_concrete_element_a(self)
def operation_a(self):
pass
class ConcreteElementB(Element):
def accept(self, visitor):
visitor.visit_concrete_element_b(self)
def operation_b(self):
pass
class Visitor:
def visit_concrete_element_a(self, element):
pass
def visit_concrete_element_b(self, element):
pass
class ConcreteVisitor1(Visitor):
def visit_concrete_element_a(self, element):
element.operation_a()
def visit_concrete_element_b(self, element):
element.operation_b()
class ConcreteVisitor2(Visitor):
def visit_concrete_element_a(self, element):
pass
def visit_concrete_element_b(self, element):
element.operation_b()
위 예제 코드에서, Element 클래스는 객체 구조의 기본 클래스입니다. ConcreteElementA와 ConcreteElementB는 실제 객체입니다. accept 메소드는 각 객체에서 호출됩니다.
Visitor 클래스는 방문자 클래스입니다. visit_concrete_element_a와 visit_concrete_element_b 메소드는 각 요소를 처리하기 위해 사용됩니다. ConcreteVisitor1과 ConcreteVisitor2는 방문자 클래스를 상속받은 구체적인 방문자 클래스입니다.
ConcreteVisitor1은 ConcreteElementA와 ConcreteElementB 객체에서 작업을 수행합니다. visit_concrete_element_a 메소드에서는 operation_a를 호출하고, visit_concrete_element_b 메소드에서는 operation_b를 호출합니다.
ConcreteVisitor2는 ConcreteElementA 객체에서는 아무 작업도 수행하지 않고, ConcreteElementB 객체에서는 operation_b를 호출합니다.
이제 이러한 클래스를 사용하여 객체 구조를 탐색하고 작업을 수행하는 방법을 살펴보겠습니다.
def main():
elements = [ConcreteElementA(), ConcreteElementB()]
visitor1 = ConcreteVisitor1()
visitor2 = ConcreteVisitor2()
for element in elements:
element.accept(visitor1)
element.accept(visitor2)
if __name__ == '__main__':
main()
main 함수에서는 ConcreteElementA와 ConcreteElementB 객체를 생성하고, ConcreteVisitor1과 ConcreteVisitor2 객체를 생성합니다.
그리고 elements 리스트에 있는 각 요소에 대해 accept 메소드를 호출하여 visitor1과 visitor2가 작업을 수행합니다.
visitor1은 ConcreteElementA와 ConcreteElementB 객체에서 모두 작업을 수행하므로, operation_a와 operation_b 메소드가 각 객체에서 호출됩니다.
visitor2는 ConcreteElementA 객체에서 아무 작업도 수행하지 않고, ConcreteElementB 객체에서는 operation_b 메소드가 호출됩니다.
이렇게 패턴을 사용하면 객체의 구조와 작업을 분리하고, 새로운 작업을 추가하거나 객체 구조를 수정하지 않고도 작업을 수행할 수 있습니다. 하지만 이 패턴은 코드가 복잡해질 수 있으므로, 상황에 따라 적합한 패턴을 선택해야 합니다.
2. 장점
- 객체 구조와 작업을 분리하므로, 새로운 작업을 추가하거나 객체 구조를 수정하지 않고도 작업을 수행할 수 있습니다.
- 객체 간의 의존성을 줄일 수 있습니다.
- 구조와 작업의 분리로 코드의 재사용성과 유지보수성을 높일 수 있습니다.
3. 단점
- 구현이 복잡해질 수 있습니다.
- 객체 구조가 바뀌면 Visitor 인터페이스와 모든 구체 Visitor 클래스를 수정해야 합니다.
- 객체 구조가 복잡해지면 방문자의 수가 증가하여 코드가 복잡해질 수 있습니다.
따라서, 객체 구조와 작업을 분리해야 하는 상황에서 Visitor 패턴은 유용한 디자인 패턴 중 하나입니다. 하지만 구조와 작업의 복잡성에 따라 패턴을 선택하고 구현하는 것이 중요합니다.
'설계' 카테고리의 다른 글
[파이썬] 포트와 어댑터 패턴 (0) | 2023.03.21 |
---|---|
[파이썬] 저장소 패턴 (Repository Pattern) 에 대해서 (0) | 2023.03.21 |
[디자인 패턴] 템플릿 메서드 패턴 (Template Method Pattern) - python 예제 코드 (0) | 2023.03.11 |
[디자인 패턴] 스트래티지 패턴 (Strategy Pattern) - python 예제 코드 (0) | 2023.03.11 |
[디자인 패턴] 스테이트 패턴 (State Pattern) - python 예제 코드 (0) | 2023.03.10 |