访问者模式

访问者模式_第1张图片
图片转载自

#include
using namespace std;
#include
/*模板工厂单例化,所有的商品被注册进工厂中*/
/*访问者模式(行为型模式)
访问者,被访问者
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类的所有类了,这也违背了开闭原则,因此我们应该认真考虑,到底我们的数据结构是定死的还是经常变化的。没有任何一种设计模式是十全十美的,总是有所取舍,有所利弊,根据实际情况来选择才是最好的设计方法。

你可能感兴趣的:(设计模式,访问者模式)