Visitor 복합객체의 연산을 수행하는 객체

알고리즘을 객체의 구조에서 분리시킨다.

-- 객체의 구조를 수정하지 않고도 실질적으로 새로운 동작을 객체 구조에 추가시킬 수 있다.

-- 컬렉션의 구조를 변하지 않고도 기능을 추가 가능하다.

-- Java에서는 Visitor Pattern을 고려하여서 사용해야 한다.

 - Composite Pattern과 연계하여 사용하는 경우가 많다.


  1. interface IVisitor<E> {
  2.         void visit(E e);
  3. }
  4.  
  5. // 방문자 허용 인터페이스
  6. interface IAcceptor<E> {
  7.         void accept(IVisitor<E> v);
  8. }
  9.  
  10. class Node<E> {
  11.         public final E data;
  12.         public final Node<E> next;
  13.  
  14.         public Node(E data, Node<E> next) { // Object
  15.                 this.data = data;
  16.                 this.next = next;
  17.         }
  18.  
  19. }
  20.  
  21. class SList<E> implements Iterable<E>, IAcceptor<E> {
  22.         private Node<E> head;
  23.  
  24.         public SList() {
  25.                 head = null;
  26.         }
  27.  
  28.         public void addFront(E n) {
  29.                 head = new Node<E>(n, head);
  30.         }
  31.  
  32.         public E front() {
  33.                 return head.data;
  34.         }
  35.  
  36.         @Override
  37.         public Iterator<E> iterator() {
  38.                 return new SListIterator<E>(head);
  39.         }
  40.  
  41.         // 외부로 노출되지 않기 위해 private class 로 구현하는게 일반적이다.
  42.         @SuppressWarnings("hiding")
  43.         private class SListIterator<E> implements Iterator<E> {
  44.                 private Node<E> current;
  45.  
  46.                 public SListIterator(Node<E> node) {
  47.                         this.current = node;
  48.                 }
  49.  
  50.                 @Override
  51.                 public boolean hasNext() {
  52.                         return current != null;
  53.                 }
  54.  
  55.                 // 현재의 요소를 반환하며 다음으로 이동
  56.                 @Override
  57.                 public E next() {
  58.                         E value = current.data;
  59.                         current = current.next;
  60.                         return value;
  61.                 }
  62.  
  63.                 @Override
  64.                 public void remove() {
  65.                         // 지원하지 않음
  66.                         throw new UnsupportedOperationException("remove() unsupported!");
  67.                 }
  68.  
  69.         }
  70.  
  71.         @Override
  72.         public void accept(IVisitor<E> v) {
  73.                 Node<E> current = head;
  74.                 while (current != null) {
  75.                         v.visit(current.data);
  76.                         current = current.next;
  77.                 }
  78.         }
  79. }
  80.  
  81. class MovePointVisitor implements IVisitor<Point> {
  82.  
  83.         private int ax;
  84.         private int ay;
  85.  
  86.         public MovePointVisitor(int ax, int ay) {
  87.                 this.ax = ax;
  88.                 this.ay = ay;
  89.         }
  90.  
  91.         @Override
  92.         public void visit(Point e) {
  93.                 e.move(this.axthis.ay);
  94.         }
  95.  
  96. }
  97.  
  98. class Point {
  99.         private int x;
  100.         private int y;
  101.  
  102.         public Point(int x, int y) {
  103.                 this.x = x;
  104.                 this.y = y;
  105.         }
  106.  
  107.         public void move(int ax, int ay) {
  108.                 this.x += ax;
  109.                 this.y += ay;
  110.                 System.out.println(this.toString());
  111.         }
  112.  
  113.         @Override
  114.         public String toString() {
  115.                 return "Point [x=" + x + ", y=" + y + "]";
  116.         }
  117.  
  118. }
  119.  
  120. // 다형성을 지원하지 않는다.
  121.  
  122. class ShowElementVisitor<extends Point> implements IVisitor<E> {
  123.  
  124.         @Override
  125.         public void visit(E e) {
  126.                 e.move(1010); // 강하게 결합된다.
  127.                 System.out.println(e.toString());
  128.         }
  129.  
  130. }
  131.  
  132. class MyPoint extends Point {
  133.         private int z;
  134.  
  135.         public MyPoint(int x, int y, int z) {
  136.                 super(x, y);
  137.                 this.z = z;
  138.         }
  139.  
  140.         @Override
  141.         public String toString() {
  142.                 return "MyPoint [z=" + z + "]";
  143.         }
  144.  
  145. }
  146.  
  147. //class MuliplyVisitor<E extends Integer> implements IVisitor<E> {
  148. //
  149. //      @Override
  150. //      public void visit(E e) {
  151. //              System.out.println(e * 2); // 한계가 있다. 다형성 구현
  152. //      }
  153. //     
  154. //}
  155. public class Ex3 {
  156.  
  157.         public static void main(String[] args) {
  158.                 SList<Point> points = new SList<>();
  159.                 points.addFront(new Point(1040));
  160.                 points.addFront(new Point(2040));
  161.                 points.addFront(new Point(3030));
  162.                 points.addFront(new Point(4020));
  163.                 points.addFront(new Point(5010));
  164.  
  165.                 for (Point point : points) {
  166.                         point.move(-10-10);
  167.                 }
  168.  
  169.                 points.accept(new MovePointVisitor(1010));
  170.  
  171.                 points.accept(new ShowElementVisitor<Point>());
  172.  
  173.                 SList<MyPoint> myPoints = new SList<>();
  174.                 myPoints.addFront(new MyPoint(10401));
  175.                 myPoints.addFront(new MyPoint(20402));
  176.                 myPoints.addFront(new MyPoint(30303));
  177.                 myPoints.addFront(new MyPoint(40204));
  178.                 myPoints.addFront(new MyPoint(50105));
  179.  
  180.         }
  181.  
  182. }


+ Recent posts