Behavioral Patterns
알고리즘이 작동하는 개체에서 알고리즘을 분리할 수 있는 패턴
Visitor는 복잡하고 적용 범위가 좁기 때문에 그리 일반적인 패턴은 아닙니다.
- Complexity: ⭐️⭐️⭐️
- Popularity: ⭐️
지리 정보를 담는 앱을 만들 때, 각 노드가 도시를 나타낼 수도 있지만 산업, 관광 지역같은 세분화된 항목도 나타낼 수 있습니다. 이때 클래스는 종류가 되고 각 객체는 특정 노드가 됩니다.
이러한 정보들을 XML로 내보내고 싶을 때 각 노드 클래스에 내보내기 기능을 추가하는 방법을 생각할 수 있습니다. 하지만 기존 노드 클래스를 변경하는 것은 예상치 않은 문제가 발생할 수 있습니다.
또한 지리를 나타내는게 주요한 노드 클래스에 해당 기능을 추가하는 것은 적합하지 않을 수 있습니다. 게다가 이후에 다른 형식으로 내보내기를 추가 요구할 가능성도 높습니다.
Visitor 패턴 새로운 동작을 기존 클래스에 통합하는 대신에 Visitor 라는 별도의 클래스를 배치합니다. 해당 기능을 수행해야 하는 개체는 Visitor 메서드 중 하나에 인수로 전달되어 해당 개체의 모든 데이터에 대한 접근을 제공합니다.
여러 유형의 인수를 가지도록 하여 다양한 객체에서 실행되도록 할 수 있습니다.
class ExportVisitor implements Visitor is
method doForCity(City c) { ... }
method doForIndustry(Industry f) { ... }
method doForSightSeeing(SightSeeing ss) { ... }
// ...
전체 그래프에서 다룰 때 이 메서드를 어떻게 호출할 수 있을까요? 해당 객체의 적절한 Visitor 메서드를 선택하려면 해당 클래스를 확인해야 합니다 😕 Visitor 패턴은 Double Dispatch를 이용하여 번거로운 조건문 없이 개체에서 적절한 메서드를 실행하게 합니다.
클라이언트가 호출할 적절한 메서드를 선택하는 일을 Visitor에게 인수로 전달할 개체에게 위임하는 것입니다. 개체는 자기 자신을 알고 있기 때문에 어렵지 않게 적절한 메서드를 선택할 수 있습니다. visitor를 accept하고 어떤 visiting method를 실행해야 하는지 알려줍니다.
비록 Node 클래스에 변경은 필요하지만 사소하게 변경을 추가해 더 많은 기능을 제공하게 할 수 있습니다.
이제 모든 visitor의 공통 인터페이스를 추출하면 모든 노드가 Visitor의 기능을 사용할 수 있고, 새로운 기능 추가하려면 새 Visitor 클래스만 구현하면 됩니다.
노련한 보험 판매자는 다양한 종류의 건물을 방문하며 보험을 판매하고자 합니다. 해당 건물의 조직에 따라 다양한 보험 정책을 제공할 수 있습니다.
ex) 주거용 건물 ➡️ 의료 보험 / 은행 ➡️ 도난 보험 / 커피숍 ➡️ 화재 및 홍수 보험
visit
메서드를 선언합니다.accept
하는 메서드를 선언합니다.accept
방법을 구현. 현재 Element 클래스에 해당하는 적절한 visit 메서드를 호출하도록visit
메서드 세트를 선언accept
메서드를 추가accept
메서드 구현. 현재 Element 클래스와 일치하는 visit
메서드를 단순히 호출하면 된다.visit
메서드를 사용해야 합니다. 반면에 Visitor는 모든 Element 클래스에 대해 알고 있어야 합니다.visit
메서드를 구현합니다.accept
를 통해 Element를 전달