概述
當我們存在一些固定的元素組合,而有一些針對這些元素的訪問者,每個訪問者針對不同的元素有不同的處理,這時候就可以採用訪問者模式。例如,電影院在放映三場電影,有很多觀衆回去看,並且給予不同的評價,這裏三場電影就是固定元素,觀衆就是訪問者;再比如,系統的某個模塊收到了一些固定的數據,有不同的模塊需要訪問並進行不同的處理,這裏數據就是固定元素,不同模塊是訪問者。
代碼實現
class Element {
public:
explicit Element(std::string name) : name_(name) {}
virtual ~Element() = default;
std::string GetName() { return name_; }
virtual void SomeOperation() = 0;
protected:
std::string name_;
};
class Element_1 : public Element {
public:
explicit Element_1(std::string name) : Element(name) {}
void SomeOperation() override {
std::cout << "Hi, I'm element 1." << std::endl;
}
};
class Element_2 : public Element {
public:
explicit Element_2(std::string name) : Element(name) {}
void SomeOperation() override {
std::cout << "Hi, I'm element 2." << std::endl;
}
};
class Visitor {
public:
virtual void ProcessElement(Element &element) = 0;
};
class Visitor_1 : public Visitor {
public:
void ProcessElement(Element &element) override {
std::cout << "I want element 1." << std::endl;
if (element.GetName() == "element1") {
element.SomeOperation();
}
};
};
class Visitor_2 : public Visitor {
public:
void ProcessElement(Element &element) override {
std::cout << "I want element 2." << std::endl;
if (element.GetName() == "element2") {
element.SomeOperation();
}
};
};
class ElementAggregation {
public:
void Add(const Element &element) { elements_.emplace_back(element); }
void AcceptVisitor(Visitor *visitor) {
for (auto &ele : elements_) {
visitor->ProcessElement(*ele);
}
}
private:
std::vector<std::unique_ptr<Element>> elements_;
};
int main() {
ElementAggregation aggregation;
aggregation.Add(Element_1("element1"));
aggregation.Add(Element_2("element2"));
Visitor *visitor_1 = new Visitor_1();
Visitor *visitor_2 = new Visitor_2();
aggregation.AcceptVisitor(visitor_1);
aggregation.AcceptVisitor(visitor_2);
}