728x90
"데이터 구조는 그대로, 기능만 확장하고 싶을 때!"
- 방문자 패턴은 객체 구조를 변경하지 않고 기능을 추가할 수 있는 강력한 패턴입니다.
- 특히 데이터 구조는 안정적이고 기능이 자주 추가되는 경우에 적합합니다.
- 하지만 새로운 데이터 구조를 추가하는 경우 유지보수가 어려울 수 있음을 고려해야 합니다.
📌 방문자 패턴의 핵심 개념
- Visitor (방문자)
- 객체의 데이터 구조를 변경하지 않고 새로운 기능을 추가하는 역할
- 객체의 내부 구조를 알 필요 없이, 방문한 객체의 accept() 메서드를 통해 적절한 동작을 수행함
- Element (요소, 데이터 구조)
- 방문자의 기능을 수락하는 역할 (accept(visitor))
- 각 요소는 Visitor 인터페이스를 구현한 객체를 받아서 적절한 방문자를 실행함
- ConcreteVisitor (구체적인 방문자)
- 실제로 각 Element를 방문하여 특정 동작을 수행하는 클래스
- 여러 개의 ConcreteVisitor를 만들어 다양한 기능을 추가 가능
- ConcreteElement (구체적인 요소)
- Element를 구현한 클래스
- accept(visitor)를 통해 방문자를 받아들이고, 방문자의 메서드를 호출하여 기능을 실행함
📌 방문자 패턴의 동작 방식
- Element는 accept(visitor: Visitor) 메서드를 제공하여 방문자를 받음.
- Visitor는 visit(elementA: ElementA)와 같은 방문 메서드를 제공.
- ConcreteElement는 accept(visitor) 메서드에서 visitor.visit(this)를 호출하여 방문자에게 자신을 넘김.
- ConcreteVisitor는 visit() 메서드를 통해 특정 요소에 대한 동작을 수행.
📌 방문자 패턴의 UML
+----------------+
| IElement |<----------------------+
| + accept() | |
+----------------+ |
▲ |
| |
+----------------+ +----------------+
| ElementA | | ElementB |
| + accept() | | + accept() |
+----------------+ +----------------+
▲ ▲
| |
+------------------+ +------------------+
| Visitor | | ConcreteVisitor |
| + visit(A) | | + visit(A) |
| + visit(B) | | + visit(B) |
+------------------+ +------------------+
📌 예제 코드 (Java)
// 1. Visitor 인터페이스
interface Visitor {
void visit(Book book);
void visit(Food food);
}
// 2. Element 인터페이스
interface Element {
void accept(Visitor visitor);
}
// 3. ConcreteElement 클래스
class Book implements Element {
String title;
public Book(String title) {
this.title = title;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
class Food implements Element {
String name;
public Food(String name) {
this.name = name;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 4. ConcreteVisitor 클래스
class DiscountVisitor implements Visitor {
@Override
public void visit(Book book) {
System.out.println("책 \"" + book.title + "\"에 할인을 적용합니다.");
}
@Override
public void visit(Food food) {
System.out.println("음식 \"" + food.name + "\"에 할인을 적용합니다.");
}
}
// 5. 사용 예시
public class VisitorPatternExample {
public static void main(String[] args) {
Element[] items = { new Book("자바 디자인 패턴"), new Food("라면") };
Visitor discountVisitor = new DiscountVisitor();
for (Element item : items) {
item.accept(discountVisitor);
}
}
}
출력 결과:
책 "자바 디자인 패턴"에 할인을 적용합니다.
음식 "라면"에 할인을 적용합니다.
📌 방문자 패턴의 장단점
✅ 장점
- 새로운 기능을 쉽게 추가할 수 있음
- 기존 데이터 구조(Element)를 수정하지 않고 새로운 기능(Visitor)을 추가 가능
- 객체 구조를 유지하면서 다양한 연산을 적용 가능
- 데이터 구조(Element)는 변경되지 않으므로 기존 시스템에 영향을 주지 않음
- OCP(Open-Closed Principle) 준수
- 요소 클래스(Element)는 수정할 필요 없이 확장이 가능
❌ 단점
- 데이터 구조가 자주 변경되는 경우 적합하지 않음
- 새로운 요소(Element)가 추가되면 모든 방문자(Visitor)를 수정해야 함
- 객체 구조가 복잡해질 수 있음
- 방문자 패턴을 적용할 경우, 요소와 방문자가 분리되어 코드가 복잡해질 수 있음
📌 방문자 패턴을 사용해야 할 때
✅ 적합한 경우
- 데이터 구조(Element)는 안정적이고, 기능(Visitor)이 자주 변경되는 경우
- 다양한 연산(통계 처리, 보고서 생성 등)을 객체에 적용해야 하는 경우
- 데이터 구조를 유지하면서, 새로운 동작을 추가해야 하는 경우
❌ 적합하지 않은 경우
- 데이터 구조(Element) 자체가 자주 변경되는 경우 (Visitor 패턴이 비효율적)
- 방문자 패턴을 적용하기 어려울 정도로 구조가 간단한 경우
📌 방문자 패턴이 사용되는 예시
- 컴파일러
- AST(Abstract Syntax Tree) 노드를 방문하여 코드 분석, 최적화, 코드 생성 수행
- XML/JSON 파서
- XML/JSON 문서의 각 노드를 방문하여 변환 또는 검증 수행
- 파일 시스템 탐색기
- 디렉토리 및 파일을 방문하여 특정 작업(예: 용량 계산, 보안 검사 등) 수행
728x90
'디자인 패턴' 카테고리의 다른 글
template method pattern (0) | 2024.07.05 |
---|---|
State Pattern (0) | 2024.06.15 |
Singletone Pattern (0) | 2024.06.15 |
Proxy Pattern (0) | 2024.06.15 |
Observer Pattern (0) | 2024.05.30 |