각 클래스 데이터 구조로부터 처리 기능을 분리하여 별도의 클래스를 만들어 놓고 해당 클래스의 메서드가 각 클래스를 돌아다니며 특정 작업을 수행하도록 만드는 패턴으로, 객체의 구조는 변경하지 않으면서 기능만 따로 추가하거나 확장할 때 사용하는 패턴이다.
이렇게 분리를 하면 구조를 수정하지 않고도 실질적으로 새로운 동작을 기존의 객체 구조에 추가할 수 있게 되기 때문에 개방-폐쇄 원칙을 적용하는 방법의 하나이다.
- Visitor: 데이터 구조 내 각각의 구체적인 요소에 visit메소드를 선언한다.
- ConcreteVisitor: Visitor 인터페이스를 구현하고, ConcreteAccepter 역할을 처리한다.
- Acceptor: Acceptor는 Visitor역할이 방문할 곳을 나타내는 역할을 하고 있다.
방문자를 받아들이는 accept메소드를 선언한다.- ConcreteAcceptor: Acceptor 인터페이스를 구현하는 역할을 한다.
- ObjectStructure: Acceptor역할의 집할을 취급하는 역할을 한다.
// Element.java (Acceptor)
public interface Element {
void accept(Visitor visitor);
}
// Cart.java (ObjectStructure)
public class Cart implements Element {
List<Element> cart = new ArrayList<>();
public Cart() {
cart.add(new Ramen("진라면 매운맛"));
cart.add(new Snack("다이제 씬"));
}
@Override
public void accept(Visitor visitor) {
System.out.println("[Cart] Cart is ready...");
visitor.visit(this);
for (Element el : cart) {
el.accept(visitor);
}
}
}
// Ramen.java (ConcreteAcceptor)
public class Ramen implements Element {
private String name;
public Ramen(String name) {
this.name = name;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
System.out.println("[Ramen] " + name + " has been picked up...");
}
}
// Snack.java (ConcreteAcceptor)
public class Snack implements Element {
private String name;
public Snack(String name) {
this.name = name;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
System.out.println("[Snack] " + name + " has been picked up...");
}
}
// Visitor.java (Visitor)
public interface Visitor {
void visit(Cart cart);
void visit(Snack snack);
void visit(Ramen ramen);
}
// Shopper.java (ConcreteVisitor)
public class Shopper implements Visitor {
@Override
public void visit(Cart cart) {
System.out.println("[Shopper] I am using a cart...");
}
@Override
public void visit(Snack snack) {
System.out.println("[Shopper] I am picking up a snack...");
}
@Override
public void visit(Ramen ramen) {
System.out.println("[Shopper] I am picking up a ramen...");
}
}
// Client.java (Client)
public class Client{
public static void main(String[] args) {
Shopper shopper = new Shopper();
Cart cart = new Cart();
cart.accept(shopper);
}
}
// 실행 결과
[Cart] Cart is ready...
[Shopper] I am using a cart...
[Ramen] 진라면 매운맛 has been picked up...
[Shopper] I am picking up a ramen...
[Snack] 다이제 씬 has been picked up...
[Shopper] I am picking up a snack...
[디자인패턴] 디자인패턴이란? - 생성패턴, 구조패턴, 행위패턴