cpp
#include<iostream>
using namespace std;
#include<list>
/*模板工厂单例化,所有的商品被注册进工厂中*/
/*访问者模式(行为型模式)
访问者,被访问者
visit accept
让访问变成一种操作,不同的访问操作有具体的实现,但是无需修改源代码(准确点说,是无需修改被访问者的源代码)
只需要增加新的具体访问类即可。局部的符合开闭原则,只是访问者类需要进行扩展和少量修改
在vitst方法中以被访问者作为参数,方法体是被访问者调用accept方法
*/
class Apple;
class Book;
class Vistor
{
public:
void set_name(std::string name)
{
_name = name;
}
virtual void visit(Apple* apple) = 0;
virtual void visit(Book* book) = 0;
protected:
std::string _name;//观察者的名字
};
class Customer :public Vistor
{
void visit(Apple* apple)
{
cout << "顾客" << _name << "挑选苹果" << endl;
}
void visit(Book* book)
{
cout << "顾客" << _name << "买书"<<endl;
}
};
class Saler :public Vistor
{
void visit(Apple* apple)
{
cout << "收银员" << _name << "称苹果" << endl;
}
void visit(Book* book)
{
cout << "收银员" << _name << "计算书价" << endl;
}
};
class Product
{
public:
virtual void accept(Vistor* vistor) = 0;
};
class Apple :public Product
{
public:
void accept(Vistor* vistor)override
{
vistor->visit(this);
}
};
class Book :public Product
{
public:
void accept(Vistor* vistor)override//在具体的被访问者类中的accept方法,参数都是访问者的父类
{
vistor->visit(this);
}
};
class ShoppingCart//管理者,可以增加或删除商品
{
public:
void accept(Vistor* vistor)
{
for (auto prd : _prd_list)
prd->accept(vistor);
}
void addProduct(Product* product)
{
_prd_list.push_back(product);
}
void removeProduct(Product* product)
{
_prd_list.remove(product);
}
private:
std::list<Product*> _prd_list;
};
int main()
{
Book book;
Apple apple;
ShoppingCart basket;
basket.addProduct(&book);
basket.addProduct(&apple);
Customer customer1;
customer1.set_name("小明");
basket.accept(&customer1);
Saler saler;
saler.set_name("小米");
basket.accept(&saler);
return 0;
}
这个示例代码写得一般,重点理解上面那张图:访问者模式就是在新增一个visitor类,visitor的visit方法定义参数为物品的抽象父类,同时在accepter中增加accept方法,accept方法参数为visitor,这样当具体访问者,调用其visit方法,方法体为accepter.accept()。
可以看到在保证accepter的数据结构不发生变化的情况下(没有新增或者删除),可以非常方便增加新的一种访问方法,只需要新增加一个访问类即可,但是如果我们数据结构发生变化之后,就需要修改继承自Visitor类的所有类了,这也违背了开闭原则,因此我们应该认真考虑,到底我们的数据结构是定死的还是经常变化的。没有任何一种设计模式是十全十美的,总是有所取舍,有所利弊,根据实际情况来选择才是最好的设计方法。