Design Pattern --- Visitor
#include <iostream> #include <vector> using namespace std; class Visitor; class Element { public: virtual void accept(Visitor &vistor) = 0; }; class Visitor { public: virtual void VisitElementA() = 0; virtual void VisitElementB() = 0; }; class VisitorA : public Visitor { public: virtual void VisitElementA() { cout <<"VisitorA::VisitElementA" <<endl; } virtual void VisitElementB() { cout <<"VisitorA::VisitElementB" <<endl; } }; class VisitorB : public Visitor { public: virtual void VisitElementA() { cout <<"VisitorB::VisitElementA" <<endl; } virtual void VisitElementB() { cout <<"VisitorB::VisitElementB" <<endl; } }; class ElementA : public Element { public: virtual void accept(Visitor &visitor) override { visitor.VisitElementA(); } }; class ElementB : public Element { public: virtual void accept(Visitor &visitor) override { visitor.VisitElementB(); } }; class ElementList { // data. vector<Element *> m_elements; public: virtual ~ElementList() { for (auto i : m_elements) { delete i; } } virtual void accept(Visitor &visitor) { for (auto i : m_elements) { i->accept(visitor); } } void pushElement(Element *element) { m_elements.push_back(element); } void popElement() { m_elements.pop_back(); } }; int main() { ElementList e; e.pushElement(new ElementA); e.pushElement(new ElementA); e.pushElement(new ElementB); VisitorA va; VisitorB vb; e.accept(va); cout <<endl; e.accept(vb); return 0; }
适用条件:
一个类聚合了多个实例的指针或者引用. (ElementList)
在 ElementList 中, 每个 Element 的实例都需要调用一个函数. 而这个函数应该是易变的.
Element 子类相对固定. 因为 Visitor 需要实现所有 Element 子类的方法.
机理:
将 "对每一个 ElementList 中的 Element 实例, 所做的某一操作" 纵向的包装成为一个类.
优点:
将易变的行为封装在单独的类中, 有利于今后扩展和修改.
一个很好的生活中的例子: