알고리즘을 객체의 구조에서 분리시킨다.
-- 객체의 구조를 수정하지 않고도 실질적으로 새로운 동작을 객체 구조에 추가시킬 수 있다.
-- 컬렉션의 구조를 변하지 않고도 기능을 추가 가능하다.
-- Java에서는 Visitor Pattern을 고려하여서 사용해야 한다.
interface IVisitor<E> {
void visit(E e);
}
// 방문자 허용 인터페이스
interface IAcceptor<E> {
void accept(IVisitor<E> v);
}
class Node<E> {
public final E data;
public final Node<E> next;
public Node(E data, Node<E> next) { // Object
this.data = data;
this.next = next;
}
}
class SList<E> implements Iterable<E>, IAcceptor<E> {
private Node<E> head;
public SList() {
head = null;
}
public void addFront(E n) {
head = new Node<E>(n, head);
}
public E front() {
return head.data;
}
@Override
public Iterator<E> iterator() {
return new SListIterator<E>(head);
}
// 외부로 노출되지 않기 위해 private class 로 구현하는게 일반적이다.
@SuppressWarnings("hiding")
private class SListIterator<E> implements Iterator<E> {
private Node<E> current;
public SListIterator(Node<E> node) {
this.current = node;
}
@Override
public boolean hasNext() {
return current != null;
}
// 현재의 요소를 반환하며 다음으로 이동
@Override
public E next() {
E value = current.data;
current = current.next;
return value;
}
@Override
public void remove() {
// 지원하지 않음
throw new UnsupportedOperationException("remove() unsupported!");
}
}
@Override
public void accept(IVisitor<E> v) {
Node<E> current = head;
while (current != null) {
v.visit(current.data);
current = current.next;
}
}
}
class MovePointVisitor implements IVisitor<Point> {
private int ax;
private int ay;
public MovePointVisitor(int ax, int ay) {
this.ax = ax;
this.ay = ay;
}
@Override
public void visit(Point e) {
e.move(this.ax, this.ay);
}
}
class Point {
private int x;
private int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public void move(int ax, int ay) {
this.x += ax;
this.y += ay;
System.out.println(this.toString());
}
@Override
public String toString() {
return "Point [x=" + x + ", y=" + y + "]";
}
}
// 다형성을 지원하지 않는다.
class ShowElementVisitor<E extends Point> implements IVisitor<E> {
@Override
public void visit(E e) {
e.move(10, 10); // 강하게 결합된다.
System.out.println(e.toString());
}
}
class MyPoint extends Point {
private int z;
public MyPoint(int x, int y, int z) {
super(x, y);
this.z = z;
}
@Override
public String toString() {
return "MyPoint [z=" + z + "]";
}
}
//class MuliplyVisitor<E extends Integer> implements IVisitor<E> {
//
// @Override
// public void visit(E e) {
// System.out.println(e * 2); // 한계가 있다. 다형성 구현
// }
//
//}
public class Ex3 {
public static void main(String[] args) {
SList<Point> points = new SList<>();
points.addFront(new Point(10, 40));
points.addFront(new Point(20, 40));
points.addFront(new Point(30, 30));
points.addFront(new Point(40, 20));
points.addFront(new Point(50, 10));
for (Point point : points) {
point.move(-10, -10);
}
points.accept(new MovePointVisitor(10, 10));
points.accept(new ShowElementVisitor<Point>());
SList<MyPoint> myPoints = new SList<>();
myPoints.addFront(new MyPoint(10, 40, 1));
myPoints.addFront(new MyPoint(20, 40, 2));
myPoints.addFront(new MyPoint(30, 30, 3));
myPoints.addFront(new MyPoint(40, 20, 4));
myPoints.addFront(new MyPoint(50, 10, 5));
}
}