본문 바로가기

💻 개발IT/Design Patterns

3. Behavior 패턴 - Visitor Pattern

Visitor Pattern

알고리즘을 Object 구조에서 분리시키는 패턴 
(OCP 적용)

목적

  • 런타임에 한 개 이상의 operation을 object 집합에 적용
  • object 집합에서 operation 분리

사용하는 경우

  • object 집합과 관련 없는 operation들이 수행되어야 하는 경우
  • object 집합(구조)는 변경할 수 없지만 operation은 변경이 빈번한 경우
  • operation이 object 집합의 concrete class에서 수행되어야하는 경우 (특히 이 object들은 각각 다른 데이터를 가지고 인터페이스도 다름)
  • operation은 같은 interface들을 구현하는 여러 object 집합에서 작동해야하는 경우

Class diagram, Sequence Diagram

  • Visitor : 각 ConcreteElement에 대한 visit operation 선언
  • ConcreteVisitor : Visitor가 선언한 visit operation을 구현
  • Element : vistor을 파라미터로 사용하는 accept operation 선언
  • ConcreteElement : vistor을 파라미터로 사용하는 accept operation 구현
  • Object Structure : element의 집합 (ex. 아래의 car class). visitor가 각 element를 방문하는데 high-level interface 제공
  • Client : ConcreteVisitor object를 생성하고, object 집합을 각 visitor와 함께 방문

장점

  • operation 추가 용이
  • object와 관련된 Operation은 object 내에, 그 외는 분리 가능

단점

  • ConcreteElement를 추가하려면, visitor, concreteVisitor에 코드 추가 필요
  • encapsulation 깨질 수 있음 - visitor 작업이 때론 ConcreteElement 내부 정보를 알 필요가 있음 (높은 결합도)

vs. Strategy Pattern

visitor는 object 내 방문하면서 operation을 하지만 strategy는 훨씬 일반적이며 내부와 특별한 연관 없음

 

예시 1

 

예시 2

시동을 걸기 위해 자동차 각 요소(바퀴, 엔진 등)가 동작하고, 출력하는 시스템 구현

 ※Car class : Composite Pattern 사용

Visitor, Element, Client 구현

ConcreteElement 구현

ConcreteVisitor 구현

 

 

예시 3 - 예시 2  + Double dispatch

더보기
  • Double dispatch (java 지원 X)
    런타임에서 method를 호출할 때 두 object에 의해 method가 결정 (ex. (a, b).method(...) )
  • Single dispatch
    method는 한 object에 의해 결정 (ex. a.method())

예시2에서 ConcreteElement 내 accept 함수를 보면 visitor.visit() 코드가 계속 반복되어 나타난다.

 

다만, 여기서 visit() 함수는 인자에 따라 다른 메소드를 호출하고 있으므로

엄연히 visit()가 아닌 accept()의 중복으로 볼 수 있다.

-> 이는 element가 추가시 accept method 작성이 필요하다는 것이다.

 

유연성을 높이기 위해 Double dispatch를 통해 수정

이를 통해 accept method는 visitor에게 함수 실행 로직을 위힘하여 실제로 기존 코드 변경 없이 accept에 대한 구현을 동적으로 변경할 수 있음

 

accept method

accept method가 실행되면, 아래 두 가지에 기반하여 실행된다.

  • element의 dynamic type
  • visitor의 static type
    파라미터로 들어와서 컴파일러가 static 타입으로 인지

 

visit method

이후 accept와 연관된 visitor method가 실행되면, 아래 두 가지에 기반하여 실행된다.

  • visitor의 dynamic type
  • element의 static type

 

결국, visist method는 element, visitor의 dynamic type으로 실행된다. 

 

 

※ traversal 구현은 어디서?

Visitor에서 구현하는 것은 피하고, (왜냐하면 visitor은 순서를 알지 못함)

되도록이면 iterator, object structure에서 

반응형