设计模式:访问者模式 C++实现


前言

今天复习了访问者模式,《大话设计模式》中说这是最难理解的一个设计模式,今天给大家分享下。


1. 访问者模式的理解

访问者模式,个人觉得,被称作操作者模式或许更符合其功用,它实现了数据结构与操作的分离,可以新增不同的操作并无需修改数据结构,满足开放-封闭原则。提到数据结构与操作分离,很容易让人想到C++ STL库,它就完美实现了数据结构与算法的分离。不过访问者模式的数据结构要求是固定的,不能变动的,否则,所有的操作也要跟着变动,这就失去了应用该设计模式的意义。

访问者模式比较正规的定义与类图(引用《大话设计模式》)如下所示:
在这里插入图片描述
在这里插入图片描述
访问者模式主要应用一种叫做双分派技术,即调用具体元素类ConcreteElement的Accept()操作需要传入访问者类,这是第一次分派;Accept()操作内应用访问这类调用其操作方法并需要传入当前具体元素类的对象作为参数,这是第二次分派。


2. C++实现访问者模式

这里《大话设计模式》中男人与女人针对不同状态的反应为例实现访问者模式。因为人类只有男人与女人,数据结构稳定,但是他们又有不同的状态反应,可以很好的解释访问者模式,该实例的类图(引用《大话设计模式》)如下所示:
在这里插入图片描述
需要注意的是,上图中定义了一个对象结构类,该类用于:针对每一种状态,分别遍历男人与女人,给出他们对应的状态反应。

C++实现代码:

#include <iostream>
#include <memory>
#include <list>

//**********************Visitor Pattern*********************
class Man;
class Woman;

//抽象状态类
class Action
{
public:
	virtual void GetManConclusion(const Man* man) = 0;
	virtual void GetWomanConclusion(const Woman* woman) = 0;
};

//成功状态类
class Success : public Action
{
public:
	virtual void GetManConclusion(const Man* man)
	{
		std::cout << "男人成功时,背后多半有一个伟大的女人" << std::endl;
	}

	virtual void GetWomanConclusion(const Woman* woman)
	{
		std::cout << "女人成功时,背后大多有一个不成功的男人" << std::endl;
	}
};

//失败状态类
class Failing : public Action
{
public:
	virtual void GetManConclusion(const Man* man)
	{
		std::cout << "男人失败时,闷头喝酒,谁也不用劝" << std::endl;
	}

	virtual void GetWomanConclusion(const Woman* woman)
	{
		std::cout << "女人失败时, 眼泪汪汪, 谁也劝不了" << std::endl;
	}
};



class Person
{
public:
	virtual void Accept(std::shared_ptr<Action> visitor) = 0;
};

class Woman : public Person
{
public:
	virtual void Accept(std::shared_ptr<Action> visitor)
	{
		visitor->GetWomanConclusion(this);
	}
};

class Man : public Person
{
public:
	virtual void Accept(std::shared_ptr<Action> visitor)
	{
		visitor->GetManConclusion(this);
	}
};

class ObjectStructure
{
private:
	std::list<std::shared_ptr<Person>> persons;

public:
	void Attach(std::shared_ptr<Person> person)
	{
		persons.push_back(person);
	}

	void Detach(std::shared_ptr<Person> person)
	{
		persons.remove(person);
	}

	void Display(std::shared_ptr<Action> visitor)
	{
		for each (auto person in persons)
		{
			person->Accept(visitor);
		}
	}
};


//**********************Test********************************
int main()
{
	std::shared_ptr<Person> smartMan = std::make_shared<Man>();
	std::shared_ptr<Person> smartWoman = std::make_shared<Woman>();

	std::shared_ptr<ObjectStructure> obj = std::make_shared<ObjectStructure>();
	obj->Attach(smartMan);
	obj->Attach(smartWoman);

	std::shared_ptr<Action> smartSuccess = std::make_shared<Success>();
	std::cout << "当成功时:" << std::endl;
	obj->Display(smartSuccess);

	std::shared_ptr<Action> smartFail = std::make_shared<Failing>();
	std::cout <<std::endl<< "当失败时:" << std::endl;
	obj->Display(smartFail);

	system("pause");
	return 0;
}

总结

《大话设计模式》中提到,该模式不常用,也很容易用错,主要针对数据结构不变,但是算法多变的应用场景。

参考

《大话设计模式》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值