C++设计模式——访问者模式
应用场景:访问者模式适用于数据结构相对文档得系统
它把数据结构和作用于结构上得操作之间得耦合脱开,是的操作集合可以相对自由得演化
目的:是要把处理从数据结构分离,按照算法和数据结构分开,如果这样子得系统有比较文档得数据结构,易于变化的算法的话,使用访问者模式是比较合适的
因为访问者模式是的算法操作的增加变得容易
优点:增加新的操作很容易,增加新的操作就意味着添加一个新的访问者 访问者模式将有关的行为集中到一个访问者对象中
缺点:使增加新的数据结构变得困难
大多数情况下,你并不需要使用访问者模式,但是当你一旦需要使用它时,那你就是需要使用它了。
举例:
一台电脑中有很多组件,CPU、GPU、硬盘。维修人员对电脑进行整体维修时,需要对各部件依次进行维修,而且每部件具体的维修方式不同。不同的维修人员对相同的部件维修方式可能也不同。
维修人员就是访问者。访问者类中实现了针对不同部件的维修方式。
电脑就是被访问者。被访问者提供访问接口,使用访问者类中实现的不同部件维修方式,对内部部件进行访问。
一台电脑中有很多组件,CPU、GPU、硬盘。维修人员对电脑进行整体维修时,需要对各部件依次进行维修,而且每部件具体的维修方式不同。不同的维修人员对相同的部件维修方式可能也不同。
维修人员就是访问者。访问者类中实现了针对不同部件的维修方式。
电脑就是被访问者。被访问者提供访问接口,使用访问者类中实现的不同部件维修方式,对内部部件进行访问。
#include <iostream> #include <list> using namespace std; class Visitor; //组成Computer的各组件基类 class Element { public: Element(string strName) :m_strName(strName) {} string GetName() { return m_strName; } //组件接受访问者访问的接口 virtual void AcceptVisitor(Visitor* pVisitor) = 0; private: //组件的标识名称 string m_strName; }; //访问者基类,针对不同组件,提供不同的访问接口 class Visitor { public: virtual void VisitCPU(Element* pEle) = 0; virtual void VisitGPU(Element* pEle) = 0; virtual void VisitDISK(Element* pEle) = 0; }; //Computer类,由各组件组成,访问者访问Computer时将依次访问各组件 class Computer { public: ~Computer() { for (Element* pElement : m_listEle) { delete pElement; } } void AddElement(Element* pEle) { m_listEle.push_back(pEle); } void DelElement(Element* pEle) { m_listEle.remove(pEle); } //访问者访问Computer时将依次访问各组件 void AcceptVisitor(Visitor* pVisitor) { for (Element* pElement : m_listEle) { pElement->AcceptVisitor(pVisitor); } } private: list<Element*> m_listEle; }; //访问者实现类,实现各自的访问方法 class VisitorA : public Visitor { public: void VisitCPU(Element* pEle) { printf("Visitor A record CPU's name:%s\n", pEle->GetName().c_str()); } void VisitGPU(Element* pEle) { printf("Visitor A do nothing to GPU:%s\n", pEle->GetName().c_str()); } void VisitDISK(Element* pEle) { printf("Visitor A change DISK:%s\n", pEle->GetName().c_str()); } }; class VisitorB : public Visitor { public: void VisitCPU(Element* pEle) { printf("Visitor B do nothing to CPU:%s\n", pEle->GetName().c_str()); } void VisitGPU(Element* pEle) { printf("Visitor B record GPU's name:%s\n", pEle->GetName().c_str()); } void VisitDISK(Element* pEle) { printf("Visitor B do nothing to DISK:%s\n", pEle->GetName().c_str()); } }; //组件的实现类,调用访问者相应的访问方法 class CPU :public Element { public: CPU(string strName) :Element(strName) {} void AcceptVisitor(Visitor* pVisitor) { pVisitor->VisitCPU(this); } }; class GPU :public Element { public: GPU(string strName) :Element(strName) {} void AcceptVisitor(Visitor* pVisitor) { pVisitor->VisitGPU(this); } }; class Disk :public Element { public: Disk(string strName) :Element(strName) {} void AcceptVisitor(Visitor* pVisitor) { pVisitor->VisitDISK(this); } }; int main() { Computer oComputer; oComputer.AddElement(new CPU("i9-10980XE")); oComputer.AddElement(new GPU("Titan RTX")); oComputer.AddElement(new Disk("HOF PRO M.2")); VisitorA oVisitorA; VisitorB oVisitorB; oComputer.AcceptVisitor(&oVisitorA); oComputer.AcceptVisitor(&oVisitorB); return 0; }
参考——大话设计模式