前言
今天复习了访问者模式,《大话设计模式》中说这是最难理解的一个设计模式,今天给大家分享下。
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;
}
总结
《大话设计模式》中提到,该模式不常用,也很容易用错,主要针对数据结构不变,但是算法多变的应用场景。
参考
《大话设计模式》