반응형
🎈 방문자 패턴 (Visitor Pattern)
•객체 구조를 변경하지 않고 객체 연산을 확장할 수 있는 패턴
• 디자인 패턴 중 행위 패턴에 해당
[예제 코드]
#include <iostream>
#include <vector>
class Book;
class Magazine;
class Visitor {
public:
virtual void visit(Book& book) = 0;
virtual void visit(Magazine& magazine) = 0;
};
class Visitable {
public:
virtual void accept(Visitor& visitor) = 0;
};
class Book : public Visitable {
public:
Book(double price) : price(price) {}
double getPrice() const {
return price;
}
void accept(Visitor& visitor) override {
visitor.visit(*this);
}
private:
double price;
};
class Magazine : public Visitable {
public:
Magazine(double price) : price(price) {}
double getPrice() const {
return price;
}
void accept(Visitor& visitor) override {
visitor.visit(*this);
}
private:
double price;
};
class PriceCalculator : public Visitor {
public:
PriceCalculator() : total(0.0) {}
void visit(Book& book) override {
total += book.getPrice();
}
void visit(Magazine& magazine) override {
total += magazine.getPrice();
}
double getTotalPrice() const {
return total;
}
private:
double total;
};
int main() {
std::vector<Visitable*> items;
items.push_back(new Book(20.0));
items.push_back(new Magazine(5.0));
items.push_back(new Book(15.0));
PriceCalculator calculator;
for (Visitable* item : items) {
item->accept(calculator);
}
std::cout << "[원가] Total price: $" << calculator.getTotalPrice() << std::endl;
return 0;
}
Book 및 Magazine 클래스에서 가격을 가져와서
PriceCalculator를 통해 총 가격을 계산한다.
Visitor 패턴을 사용하면 기존 클래스를 수정하지 않고
새로운 연산을 쉽게 추가할 수 있다.
[예제 코드]
특정 %{percent} 할인율 가격 확인하는 방문자 Class 추가
#include <iostream>
#include <vector>
class Book;
class Magazine;
class Visitor {
public:
virtual void visit(Book& book) = 0;
virtual void visit(Magazine& magazine) = 0;
};
class Visitable {
public:
virtual void accept(Visitor& visitor) = 0;
};
class Book : public Visitable {
public:
Book(double price) : price(price) {}
double getPrice() const {
return price;
}
void accept(Visitor& visitor) override {
visitor.visit(*this);
}
private:
double price;
};
class Magazine : public Visitable {
public:
Magazine(double price) : price(price) {}
double getPrice() const {
return price;
}
void accept(Visitor& visitor) override {
visitor.visit(*this);
}
private:
double price;
};
class PriceCalculator : public Visitor {
public:
PriceCalculator() : total(0.0) {}
void visit(Book& book) override {
total += book.getPrice();
}
void visit(Magazine& magazine) override {
total += magazine.getPrice();
}
double getTotalPrice() const {
return total;
}
private:
double total;
};
class PriceDiscount : public Visitor {
public:
PriceDiscount() {}
void visit(Book& book) override {
std::cout << "[" << percent << "% 할인] 책: " \
<< getDiscount(book.getPrice()) << std::endl;
}
void visit(Magazine& magazine) override {
std::cout << "[" << percent << "% 할인] 잡지: " \
<< getDiscount(magazine.getPrice()) << std::endl;
}
double getDiscount(double price) {
return price - (price * percent / 100);
}
void setPercent(int _percent) {
percent = _percent;
}
private:
int percent;
};
int main() {
std::vector<Visitable*> items;
items.push_back(new Book(20.0));
items.push_back(new Magazine(5.0));
items.push_back(new Book(15.0));
PriceCalculator calculator;
for (Visitable* item : items) {
item->accept(calculator);
}
std::cout << "[원가] Total price: $" << calculator.getTotalPrice() << std::endl;
PriceDiscount discountor;
discountor.setPercent(50);
for (Visitable* item : items) {
item->accept(discountor);
}
return 0;
}
Visitor 인터페이스를 정의하여 새로운 연산(로직) 추가
마찬가지로 accept 메서드를 통해 방문자를 받아들일 수 있게 한다.
🎈 방문자 패턴 장단점
+ 연산의 분리: 객체 구조와 연산을 독립적으로 확장 및 변경할 수 있다.
+ 단일 책임 원칙: 각 클래스는 자신의 상태와 연산에만 집중할 수 있다
- 결합도 증가: 객체 구조의 각 요소가 모든 방문자를 인식해야 하므로,
클래스 간의 결합도가 증가할 수 있다.
- 유지 보수: 새로운 요소나 방문자를 추가할 때,
모든 방문자 클래스에 새로운 메서드 구현 필요하다.
반응형
'까망 동네 > 디자인 패턴' 카테고리의 다른 글
객체 지향 프로그래밍 5대 원칙 [SOLID] (40) | 2023.11.19 |
---|---|
[디자인 패턴] 반복자 패턴(Iterator Pattern) (33) | 2023.11.14 |
[디자인 패턴] 경량 패턴 (Flyweight Pattern) (2) | 2023.11.12 |
[디자인 패턴] 프록시 패턴 (Proxy Pattern) (3) | 2023.11.11 |
[디자인 패턴] 메멘토 패턴 (Memento Pattern) (1) | 2023.11.10 |
댓글