티스토리 뷰

Java

Visitor Pattern 배워보기

techbard 2014.01.28 21:46

비지터 패턴은 보통 한 클래스 내에 존재해야 할 데이터와 메소드를 다른 클래스로 분리하여 서로 간에 호출하도록 함으로써 향후 메소드 추가를 자유롭게 하려는 패턴이다. 즉 객체는 그대로 둔 채 객체에 대한 연산을 분리한다고 한다.

 

먼저 개념상 방문자가 방문을 하여야 하는 대상을 정의한다.

 

1. 대상 객체 클래스들이 방문자를 허용해야 하므로 그 방문자 객체를 받아들인다는 의미의 인터페이스를 작성한다.

 

 

이제 대상 객체들은 모두 이 인터페이스를 구현해야 한다.

 

2. 가장 먼저 대상 객체들을 담을 객체를 만든다. 그래야 순회하면서 모든 객체를 호출할 수 있기 때문이다.

 

 

생성자에서 나머지 객체들을 멤버 자료구조에 추가하며 accept() 메소드를 구현했다. 이 부분이 진입지점이 되는데

 

15번 라인에서 먼저 Cart 객체 자기 자신을 Visitor 객체의 visit() 메소드에 던진다. 아직 Visitor 인터페이스를 구현한 클래스는 나오지 않았으니 여기까지 하자. 이후 나머지 객체들에 대해서 해당 객체의 accept() 메소드에 visitor 객체를 담아 호출한다.

 

3. 나머지 객체들도 구조는 동일하다. 호출받으면 다시 역 호출하면서 자기 자신을 던지는 구조로 되어 있다.

 

 

 

4. 이제 Visitor 인터페이스를 구현해 보자. 앞에서 visit() 메소드에 각각 객체들 자신을 담아서 던지고 있으므로 인터페이스에도 이를 정의해야 한다. 동일한 visit() 메소드지만 overloading을 이용해 서로 다른 객체를 다 처리한다.

 

 

5. 이 Visitor 인터페이스를 구현한 클래스를 작성한다. 실제 일을 하는 메소드 본체가 들어 있는 클래스이다.

 

 

Visitor 인터페이스에서 오버로딩으로 정의했기 때문에 이를 구현한 Shopper 클래스에서도 각 객체타입마다의 visit() 메소드를 정의했다. 이제 visit() 메소드에 담겨 호출되는 객체의 종류에 따라 제각기 다른 visit() 메소드가 호출될 것이다.

 

6. 테스트 클래스로 확인해 보자.

 

 

결과:

Cart가 준비되었습니다.
Cart를 이용합니다.
과일이 준비되었습니다.
과일을 넣었습니다.
우유가 준비되었습니다.
우유를 넣었습니다.

이제 전체적인 흐름을 따라가 보면,

 

테스트 클래스의 6번 라인에서

1. cart의 accept() 메소드에 비지터를 구현한 shopper를 던진다.

2. cart의 accept() 메소드에서는 다시 비지터의 visit() 메소드에 cart 자신 객체를 담아 던진다.

3. 다시 Shopper 클래스에 넘어온 객체는 cart이므로 Shopper 클래스의 5번 라인이 실행된다.

4. 여기까지 Cart 클래스의 15번 라인까지 수행되었고

5. 나머지 객체들인 Fruits와 Milk에 대해서 위에서 받은 visitor를 이용해

6. Fruits.accept(visitor)가 실행되고 이는 다시 호출한 Visitor 클래스 내의 Fruits 객체를 받는 visit() 메소드

7. Milk.accept(visitor)가 실행되고 이는 다시 호출한 Visitor 클래스 내의 Milk 객체를 받는 visit() 메소드가 각각 호출된다.

 

이런 결과로 Element 인터페이스를 구현한 3개의 객체가 Visitor를 구현한 Shopper 클래스를 호출하면서 자신의 객체 타입에 맞는 메소드를 호출하게 된다.

 

VisitorPattern.zip

 

 

댓글
댓글쓰기 폼
공지사항
Total
409,794
Today
12
Yesterday
27
«   2019/11   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함