访问者模式(Facade),表示一个作用于某对象结构中的各个元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
分析:该模式相对来说比较复杂,要详细拆解一下定义和类图才能拨云见日。
首先我们再看一下定义:访问者模式表示一个作用于某对象结构(ObjectStruct)中的各个元素(Person)的操作(Action)。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
此具体实现中Action及其子类代表可变的行为,Person及其子类代表稳定不变的数据结构。
一句话的定义其实已经把该模式对应的UML类图给我们勾勒出来了。定义的第一句话用那么长的修饰语最后就定义了两个黑体字操作,所以说访问者模式就是操作作为访问者的模式。接下来我们对应代码好好分析一下我们理出来关键信息,我们找出了如下关键字并逐一分析:
对象结构:
用来保存各个元素,可以把它理解为一个数据结构的管理类。
元素:
元素就是我们定义的一个个的Action实例,它用来访问对象结构里面的元素。这里面有一个双分派的技术,就是数据结构Person对象的accept方法接收到一个方法Action对象,然后Action的对应的方法(PerformanceMan
,PerformanceWoman
)再把this
指针传送进去,这样就完成了Action在ObjectStruct中的对对象容器的遍历访问,其实Person对象也相当于把Action注册到了自己的类内。
操作:
Action对象,是可变的。需要增加新的操作的时候只需要创建一个新的继承Action的类即可。然后通过ObjectStruct::Display(Action);
执行。
这5个步骤很清晰的写出了整个模式的关键步骤。
操作基类
class Action
{
public:
Action();
~Action();
virtual void PerformanceMan(Man* man){};
virtual void PerformanceWoman(Woman* woman){};
};
再来贴一个具体的实现类:
#include "success.h"
#include <iostream>
Success::Success()
:m_Type("成功")
{
}
void Success::PerformanceMan(Man* man)
{
std::cout << man->Type() << this->m_Type << "时候的表现" << std::endl;
}
void Success::PerformanceWoman(Woman* woman)
{
std::cout << woman->Type() << this->m_Type << "时候的表现" << std::endl;
}
我们可以看到两个虚函数PerformanceMan
和PerformanceWoman
就是用来访问具体的Person(数据结构)
对象的,所以说该模式适合在数据结构固定的场景使用,不然每增加一个Person子类我们都要增加Action
的虚方法,用来访问新增加的Person子类,显然不符合开放封闭原则,而且Action的每一个子类都要增加相应的实现。
#include "person.h"
#include "action.h"
#include <vector>
#include <list>
class ObjectStruct
{
public:
ObjectStruct();
void Display(Action* action);
void Attach(Person* person);
void Detach(Person* person);
std::list<Person* > m_Person;
};
#include "objectstruct.h"
ObjectStruct::ObjectStruct()
{
}
void ObjectStruct::Display(Action* action)
{
for(auto person : m_Person)
{
person->Accept(action);
}
}
void ObjectStruct::Attach(Person *person)
{
m_Person.push_back(person);
}
void ObjectStruct::Detach(Person *person)
{
m_Person.remove(person);
}
Action.h
#include "man.h"
#include "woman.h"
class Action
{
public:
Action();
~Action();
virtual void PerformanceMan(Man* man){};
virtual void PerformanceWoman(Woman* woman){};
};
person.h
class Action;
class Person
{
public:
Person();
virtual void Accept(Action* action);
};
#include "action.h"
class Success : public Action
{
public:
Success();
void PerformanceMan(Man* woman) override;
void PerformanceWoman(Woman* woman) override;
private:
std::string m_Type;
};
#include "success.h"
#include <iostream>
Success::Success()
:m_Type("成功")
{
}
void Success::PerformanceMan(Man* man)
{
std::cout << man->Type() << this->m_Type << "时候的表现" << std::endl;
}
void Success::PerformanceWoman(Woman* woman)
{
std::cout << woman->Type() << this->m_Type << "时候的表现" << std::endl;
}
#include "person.h"
#include <string>
class Man : public Person
{
public:
Man();
void Accept(Action* action) override;
std::string Type();
private:
std::string m_Type;
};
#include "man.h"
#include "action.h"
Man::Man()
: m_Type("男人")
{
}
void Man::Accept(Action *action)
{
action->PerformanceMan(this);
}
std::string Man::Type()
{
return m_Type;
}
#include <iostream>
#include "objectstruct.h"
#include "man.h"
#include "woman.h"
#include "success.h"
#include "failed.h"
#include "married.h"
#include "breakup.h"
using namespace std;
int main()
{
ObjectStruct obj;
Man* man = new Man();
obj.Attach(man);
Woman*woman = new Woman();
obj.Attach(woman);
Success* success = new Success();
obj.Display(success);
Failed* failed = new Failed();
obj.Display(failed);
Married* married = new Married();
obj.Display(married);
BreakUp* breakUp = new BreakUp();
obj.Display(breakUp);
return 0;
}
其他相似的子类的详细代码就不列出了
运行结果
男人成功时候的表现
女人成功时候的表现
男人失败时候的表现
女人失败时候的表现
男人婚后时候的表现
女人婚后时候的表现
男人分手时候的表现
女人分手时候的表现
访问者模式的优点
模式的缺点
原文:https://www.cnblogs.com/wzxNote/p/13278443.html