Updated:

1. 개요

연산을 적용할 원소의 클래스를 변경하지 않고도 새로운 연산을 정의할 수 있도록 하는 패턴

방문자 패턴(Visitor Pattern)은 행동 패턴(Behavioral Pattern)의 한 종류로, 데이터 구조와 연산을 분리하여 데이터 구조의 원소들을 변경하지 않고, 방문자를 추가하여 새로운 연산을 추가할 수 있는 패턴이다.

2. 행동 패턴(Behavioral Pattern)

2-1. 행동 패턴이란?

행동 패턴이란 처리의 책임을 어떤 객체에게 할당하는 것이 좋은지, 알고리즘을 어떤 객체에 정의하는 것이 좋은지 등의 책임 분배와 관련된 패턴이다.

2-2. 행동 패턴 종류

3. 구성

[출처 : GoF의 디자인 패턴]

  • Visitor : visit 연산을 정의한 인터페이스

  • ConcreteVisitor : Visitor 인터페이스 구현체

  • Element : accept 연산을 정의한 인터페이스

  • ConcreteElement : Element 인터페이스 구현체

  • ObjectStructure : 원소들을 나열해놓은 클래스

4. 예제 코드

Visitor Pattern을 이용하여 로봇을 구성하는 과정을 코드로 구현해보자.

4-1. Element

[RobotPart.java]

1
2
3
4
public interface RobotPart {

    void accept(RobotPartVisitor robotPartVisitor);
}

4-2. ConcreteElement

[Helmet.java]

1
2
3
4
5
6
7
public class Helmet implements RobotPart {

    @Override
    public void accept(RobotPartVisitor robotPartVisitor) {
        robotPartVisitor.visit(this);
    }
}

[Armor.java]

1
2
3
4
5
6
7
public class Armor implements RobotPart {

    @Override
    public void accept(RobotPartVisitor robotPartVisitor) {
        robotPartVisitor.visit(this);
    }
}

4-3. Visitor

[RobotPartVisitor.java]

1
2
3
4
5
6
public interface RobotPartVisitor {

    void visit(Robot robot);
    void visit(Helmet helmet);
    void visit(Armor armor);
}

4-4. RobotPartDisplayVisitor

[RobotPartVisitor.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class RobotPartDisplayVisitor implements RobotPartVisitor {

    @Override
    public void visit(Robot robot) {
        System.out.println("Displaying Robot");
    }

    @Override
    public void visit(Helmet helmet) {
        System.out.println("Displaying Helmet");
    }

    @Override
    public void visit(Armor armor) {
        System.out.println("Displaying Armor");
    }
}

4-5. ObjectStructure

[Robot.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Robot implements RobotPart {

    private RobotPart[] parts;

    public Robot() {
        this.parts = new RobotPart[] {new Helmet(), new Armor()};
    }

    @Override
    public void accept(RobotPartVisitor robotPartVisitor) {
        for (RobotPart part : parts) {
            part.accept(robotPartVisitor);
        }
        robotPartVisitor.visit(this);
    }
}

5. 테스트

[Clinet.java]

1
2
3
4
5
6
7
public class Client {

    public static void main(String[] args) {
        RobotPart robot = new Robot();
        robot.accept(new RobotPartDisplayVisitor());
    }
}

[실행 결과]

6. 특징

  • 기능 추가의 용이성 : Visitor를 추가하여 기능 추가가 쉬움

  • 동일한 인터페이스 제공 : 사용자에게 동일한 인터페이스를 제공

  • 높은 결합성 : Element가 추가되면 Visitor도 추가 필요

Updated:

Leave a comment