Hello

[디자인 패턴] - Visitor

by 볼빵빵오춘기

Visitor

객체 구조에서 변경 없이, 새로운 기능을 추가하고 싶을 때 사용하는 디자인 패턴이다.

기능(로직)을 방문자(Visitor) 객체로 분리해서, 객체 구조(Element)는 그대로 두고, 새로운 연산을 Visitor 객체에 넣는 방식이다.

즉, "로직을 객체 밖으로 분리" 하는 구조이다.

 

예시 코드

// 방문 가능한 Element 인터페이스
interface Element {
    void accept(Visitor visitor);
}

// 구체적인 요소
class Keyboard implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

class Monitor implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

// 방문자 인터페이스
interface Visitor {
    void visit(Keyboard keyboard);
    void visit(Monitor monitor);
}

// 방문자 구현: 가격 계산
class PriceCalculator implements Visitor {
    public void visit(Keyboard keyboard) {
        System.out.println("Keyboard 가격은 10만원입니다.");
    }

    public void visit(Monitor monitor) {
        System.out.println("Monitor 가격은 30만원입니다.");
    }
}

// 사용 예제
public class VisitorExample {
    public static void main(String[] args) {
        Element[] items = { new Keyboard(), new Monitor() };
        Visitor visitor = new PriceCalculator();

        for (Element item : items) {
            item.accept(visitor);  // 방문자에게 각 요소를 전달
        }
    }
}

 

Visitor 패턴의 장점

기능 확장 용이

객체 구조를 수정하지 않고도 새로운 기능 추가 가능하다. (OCP 만족)

 

객체 구조와 기능 분리

방문자가 로직을 담당하므로 객체 구조는 단순하게 유지 가능하다.

 

객체별 동작 일괄 구현 가능

다양한 타입에 따라 다르게 동작하는 로직을 하나의 Visitor에 통합 가능하다.

 

복잡한 구조 탐색에 유리

트리나 컴포지트 구조 등 계층적인 데이터에 적합하다.

 

Visitor 패턴의 단점

객체 구조 변경 시 귀찮음

Element에 새로운 타입이 생기면 모든 Visitor를 수정해야 함

 

이중 디스패치 복잡성

Java/C++처럼 싱글 디스패치 언어에서 구현 시 난해할 수 있다.

 

객체와 기능이 멀어짐

로직이 Visitor에 있기 때문에, 유지보수 시 추적이 힘들 수 있다.

 

Visitor 패턴은 언제 사용하나?

객체 구조는 안정적이고, 기능이 자주 변경될 때

구조는 그대로 두고 기능만 자주 바뀌는 경우

 

여러 종류의 객체에 대해 서로 다른 동작을 해야 할 때

ex) 요소마다 다르게 처리하는 경우 (리포트 생성 등)

 

복잡한 구조(트리, 컴포지트 등)를 탐색하며 작업할 때

XML 파서, 문서 렌더러, 컴파일러 등에서 자주 사용

 

정리하자면

객체 구조는 그대로 두고, 기능(로직)을 외부 객체(Visitor)로 분리해 새로운 연산을 유연하게 추가할 수 있는 패턴이다.

 

블로그의 정보

Hello 춘기's world

볼빵빵오춘기

활동하기