设计模式之访问者模式-访问一下呗!
访问者模式
一、访问者模式的概念
访问者模式属于行为模式,它分离对象的数据和行为,使用访问者模式,可以在不修改已有类的情况下,增加新的操作角色和职责。
二、访问者模式使用场景
1、当对象结构中的对象对应的类很少改变,但经常需要在此对象结构上定义新的行为和操作方法。
2、当需要对对象结构新增加的行为和操作,避免新的操作和行为改变原来的对象类,可以使用该模式实现解耦合。
三、访问者模式构建方法
1、抽象访问者类(Visitor)
访问者的对象抽象类,定义具体访问者的共同接口和方法。
2、具体访问者类(ConcreteVisitor)
具体访问者类实现抽象访问者类所声明的接口和方法。
3、抽象节点类(Element)
抽象节点类声明一个接受接口和方法,接受一个访问者对象作为一个参量。
4、具体节点类(ConcreteElement)
具体节点类实现了抽象节点类所定义的的接受接口和方法。
5、结构对象类(ObiectStructure)
结构对象类可以遍历结构中的所有元素,可以提供一个高层次的接口,让访问者对象可以访问每一个元素。
四、访问者模式的示例
// VisitorPattern.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
#include <list>
#define DELETE_PTR(p) {if(p!=nullptr){delete (p); (p)=nullptr;}}
using namespace std;
// 前置声明
class StaffElement;
// 访问者抽象类-客户
class CustomerVisit
{
public:
virtual void customVisit(StaffElement *pStaffElement) = 0;
};
// 抽象节点类-营业厅员工
class StaffElement
{
public:
virtual void accepCustomer(CustomerVisit *CustomerVisit) = 0;
virtual string getName() = 0;
};
// 具体节点类-营业厅员工A
class StaffAElem : public StaffElement
{
public:
StaffAElem(string nameStr)
{
m_nameStr = nameStr;
}
virtual void accepCustomer(CustomerVisit *pCustomerVisit)
{
pCustomerVisit->customVisit(this);
}
virtual string getName()
{
return m_nameStr;
}
private:
string m_nameStr;
};
// 具体节点类-营业厅员工B
class StaffBElem : public StaffElement
{
public:
StaffBElem(string nameStr)
{
m_nameStr = nameStr;
}
virtual void accepCustomer(CustomerVisit *pCustomerVisit)
{
pCustomerVisit->customVisit(this);
}
virtual string getName()
{
return m_nameStr;
}
private:
string m_nameStr;
};
// 具体访问者类-客户A
class CustomerAVisit : public CustomerVisit
{
public:
virtual void customVisit(StaffElement *pStaffElement)
{
cout << "客户A在营业厅里通过->" << pStaffElement->getName() << "办理业务" << endl;
}
};
// 具体访问者类-客户B
class CustomerBVisit : public CustomerVisit
{
public:
virtual void customVisit(StaffElement *pStaffElement)
{
cout << "客户B在营业厅里通过->" << pStaffElement->getName() << "办理业务" << endl;
}
};
// 结构对象类-员工管理类
class StaffStructure : public StaffElement
{
public:
StaffStructure()
{
m_staffElemList.clear();
}
~StaffStructure()
{
for (auto iter : m_staffElemList)
{
DELETE_PTR(iter);
}
m_staffElemList.clear();
}
virtual void accepCustomer(CustomerVisit *pCustomerVisit)
{
for (auto iter : m_staffElemList)
{
iter->accepCustomer(pCustomerVisit);
}
}
string getName()
{
return m_nameStr;
}
void addStaffElem(StaffElement *pStaffElement)
{
m_staffElemList.push_back(pStaffElement);
}
void removeStaffElem(StaffElement *pStaffElement)
{
m_staffElemList.remove(pStaffElement);
}
private:
list<StaffElement*> m_staffElemList;
string m_nameStr;
};
int main()
{
cout << "----------------------访问者模式-------------------------" << endl;
StaffAElem *pStaffAElem = new StaffAElem("营业厅员工A");
StaffBElem *pStaffBElem = new StaffBElem("营业厅员工B");
StaffStructure *pStaffStructure = new StaffStructure;
pStaffStructure->addStaffElem(pStaffAElem);
pStaffStructure->addStaffElem(pStaffBElem);
CustomerAVisit *pCustomerAVisit = new CustomerAVisit;
CustomerBVisit *pCustomerBVisit = new CustomerBVisit;
cout << "------------客户A办理业务--------------" << endl;
pStaffStructure->accepCustomer(pCustomerAVisit);
cout << "------------客户B办理业务--------------" << endl;
pStaffStructure->accepCustomer(pCustomerBVisit);
//DELETE_PTR(pStaffAElem); //已经在StaffStructure析构函数析构
//DELETE_PTR(pStaffBElem);
DELETE_PTR(pCustomerAVisit);
DELETE_PTR(pCustomerBVisit);
DELETE_PTR(pStaffStructure);
std::cout << "Hello World!\n";
getchar();
}
运行结果:
五、访问者模式的优缺点
优点:
1、每一个类都有自己的明确职责,符合单一职责原则。
2、访问者模式增加新的操作很容易,扩展性和灵活性好。
缺点:
1、增加新的节点类比较困难,每增加一个新的节点都要在抽象访问类中增加
一个新的抽象接口和方法,并在每一个具体访问者类中增加相应的具体接口和方法。
2、破坏封装,具体节点类必须对外暴露自己的内部状态和操作方法。
爱人生,爱微笑,一个爱分享的程序员。
能力有限,如有错误,多多指教。。。
本文为博主原创文章,未经博主允许请勿转载!作者:ISmileLi