방문자 패턴은 개체의 구조와 개체가 수행하는 작업을 분리하는 디자인 패턴이다. 개체의 구조는 변경하지 않고, 새로운 작업을 개체에 추가할 수 있다. 방문자 패턴은 주로 개체 구조가 자주 변경되지만, 수행해야할 작업이 자주 변경된는 경우에 유용하다.
주요 개념 부터 살펴보자.
1. Visitor(방문자) : 개체 구조를 방문하여 수행할 작업을 정의하는 인터페이스이다.
2. ConcreteVisitor(구체적인 방문자) : Visitor 인터페이스를 구현하며, 각 개체에 대해 수행할 작업을 정의한다.
3. Element(요소) : Visitor를 받아들이는 인터페이스이다. 이 인터페이스는 accept 메서드를 정의한다.
4. ConcreteElement(구체적인 요소) : Element 인터페이스를 구현하며 accept 메서드에서 Visitor를 받아들인다.
5. ObjectStructure(개체 구조) : 개체 구조를 관리하면, Visitor 를 받아들여 각 요소를 방문하도록 한다.
예시 소스 코드로 확인해보자.
쇼핑몰에서 할인을 적용하는 로직을 구현해본다.
interface DiscountVisitor {
void visit(Book book);
void visit(Electronics electronics);
}
class DiscountCalculator implements DiscountVisitor {
private double totalDiscount = 0.0;
@Override
public void visit(Book book) {
double discount = book.getPrice() * 0.10; // 책은 10% 할인
totalDiscount += discount;
System.out.println("Book Discount: " + discount);
}
@Override
public void visit(Electronics electronics) {
double discount = electronics.getPrice() * 0.20; // 전자 제품은 20% 할인
totalDiscount += discount;
System.out.println("Electronics Discount: " + discount);
}
public double getTotalDiscount() {
return totalDiscount;
}
}
interface Item {
void accept(DiscountVisitor visitor);
}
class Book implements Item {
private double price;
public Book(double price) {
this.price = price;
}
public double getPrice() {
return price;
}
@Override
public void accept(DiscountVisitor visitor) {
visitor.visit(this);
}
}
class Electronics implements Item {
private double price;
public Electronics(double price) {
this.price = price;
}
public double getPrice() {
return price;
}
@Override
public void accept(DiscountVisitor visitor) {
visitor.visit(this);
}
}
import java.util.ArrayList;
import java.util.List;
class ShoppingCart {
private List<Item> items;
public ShoppingCart() {
items = new ArrayList<>();
}
public void addItem(Item item) {
items.add(item);
}
public void applyDiscounts(DiscountVisitor visitor) {
for (Item item : items) {
item.accept(visitor);
}
}
}
public class VisitorPatternShoppingDemo {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
cart.addItem(new Book(100));
cart.addItem(new Electronics(200));
DiscountCalculator discountCalculator = new DiscountCalculator();
cart.applyDiscounts(discountCalculator);
System.out.println("Total Discount: " + discountCalculator.getTotalDiscount());
}
}
// 출력
//Book Discount: 10.0
//Electronics Discount: 40.0
//Total Discount: 50.0
각 상품에 대해 다른 할인율을 적용하고 총 할인 금액을 계산하는 작업을 Visitor 개체에 위임했다. 이렇게 하면 상품의 구조는 변경하지 않고도 할인 계산 로직을 Visitor 개체에 추가하거나 변경할 수 있다.
방문자 패턴은 연선을 새로 추가하고 개체 구조와 연산을 분리함으로써 독립적으로 관리할 수 있다는 장점이 있지만 개체 구조가 자주 변경되면 비효율 적일 수 있다. 또한 방문자가 개체의 내부 상태에 접근해야해서 개체의 캡슐화가 위반될 수 있다.
'Design Pattern > 행동 패턴(Behavioral Patterns)' 카테고리의 다른 글
템플릿 메서드(Template Method) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
---|---|
전략(Strategy) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
상태(State) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
옵저버(Observer) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |
메멘토(Memento) - 행동 패턴(Behavioral Patterns) (0) | 2024.05.25 |