[디자인 패턴] 방문자 패턴_ Visitor pattern (JavaScript)
2024. 11. 17. 21:50ㆍWeb_Programming
Visitor 패턴이란?
Visitor 패턴은 객체 구조를 변경하지 않고도 새로운 연산을 추가할 수 있도록 하는 행동 디자인 패턴입니다. 데이터 구조와 알고리즘의 분리를 통해, 데이터 객체는 그대로 두고 외부에서 로직을 확장할 수 있습니다.
구성요소
Visitor 인터페이스
- 데이터 구조의 각 요소에 대해 수행될 연산을 선언합니다.
- 메서드 이름과 매개변수는 구체적인 요소 타입에 따라 달라집니다.
interface Visitor { visitConcreteElementA(element: ConcreteElementA): void; visitConcreteElementB(element: ConcreteElementB): void; }
ConcreteVisitor
- Visitor 인터페이스를 구현하며, 각 요소 타입에 대해 구체적인 작업을 수행합니다.
- 예: 알림 전송, 로그 기록 등
class ConcreteVisitorA implements Visitor { visitConcreteElementA(element: ConcreteElementA): void { console.log("VisitorA processing ElementA"); } visitConcreteElementB(element: ConcreteElementB): void { console.log("VisitorA processing ElementB"); } }
Element 인터페이스
- Visitor를 받아들이는 역할로,
accept(visitor: Visitor)
메서드를 정의합니다.interface Element { accept(visitor: Visitor): void; }
ConcreteElement
- Element 인터페이스를 구현하며,
accept
메서드에서 Visitor 객체를 호출합니다.class ConcreteElementA implements Element { accept(visitor: Visitor): void { visitor.visitConcreteElementA(this); } }
예시 코드
주문 처리 시스템을 예시로,
- 각 주문 상태(Pending, Shipped 등)를 ConcreteElement로 표현합니다.
- 알림(Notification)과 로깅(Logging) 작업을 수행할 방문자 클래스를 구현합니다.
// Element 인터페이스 및 구현체
interface Order {
accept(visitor: OrderVisitor): void;
}
class PendingOrder implements Order {
constructor(public orderId: string) {}
accept(visitor: OrderVisitor): void {
visitor.visitPendingOrder(this);
}
}
class ShippedOrder implements Order {
constructor(public orderId: string, public trackingNumber: string) {}
accept(visitor: OrderVisitor): void {
visitor.visitShippedOrder(this);
}
}
// Visitor 인터페이스 및 구현체
interface OrderVisitor {
visitPendingOrder(order: PendingOrder): void;
visitShippedOrder(order: ShippedOrder): void;
}
class NotificationVisitor implements OrderVisitor {
visitPendingOrder(order: PendingOrder): void {
console.log(`Notifying pending order: ${order.orderId}`);
}
visitShippedOrder(order: ShippedOrder): void {
console.log(`Notifying shipped order: ${order.orderId} (Tracking: ${order.trackingNumber})`);
}
}
// 사용
const orders: Order[] = [
new PendingOrder("O-001"),
new ShippedOrder("O-002", "TRACK-123"),
];
const notificationVisitor = new NotificationVisitor();
orders.forEach(order => order.accept(notificationVisitor));
사용 상황
- 객체 구조는 변경되지 않고 그대로 유지해야 하지만, 새로운 동작을 추가해야 할 때.
- 데이터와 관련 연산이 서로 다른 클래스로 분리되어야 할 때.
- 작업 대상이 복잡한 객체 구조(예: 트리 구조)일 때.
장점
- 연산 추가가 용이
- 데이터 구조를 수정하지 않고도 새로운 동작(연산)을 추가할 수 있습니다.
- 데이터와 연산의 분리
- 데이터 객체는 자료 구조에 집중하고, 알고리즘은 Visitor 객체로 분리하여 유연성을 높입니다.
- 코드 확장성
- 다양한 Visitor를 생성해 기존 데이터 구조에 새로운 동작을 쉽게 추가 가능.
단점
- 높은 결합도
- Visitor와 Element 간의 의존도가 높아집니다.
- 새로운 요소 추가의 어려움
- 새로운 데이터 구조(ConcreteElement)가 추가될 경우, 모든 Visitor에 수정이 필요합니다.
반응형
'Web_Programming' 카테고리의 다른 글
[디자인 패턴] 반복자 패턴_Iterator pattern (JavaScript) (0) | 2024.11.17 |
---|---|
[디자인 패턴] 복합체 패턴_ Composite pattern (JavaScript) (0) | 2024.11.17 |
[디자인 패턴] 플라이웨이트 패턴_ Flyweight pattern (JavaScript) (0) | 2024.11.17 |
[디자인 패턴] 관찰자 패턴_Observer pattern (JavaScript) (0) | 2024.11.17 |
[디자인 패턴] 어댑터 패턴_Adapter pattern (JavaScript) (0) | 2024.11.17 |