访问者模式
什么是访问者模式
访问者模式是行为模式之一,它分离对象的数据和行为,使用访问者模式模式,可以不修改已有类的情况下,增加新的操作角色和职责
为什么使用访问者模式
访问者模式通过在访问者对象中为多个目标类提供相同操作的变体, 让你能在属于不同类的一组对象上执行同一操作;访问者模式将所有非主要的行为抽取到一组访问者类中, 使得程序的主要类能更专注于主要的工作;当某个行为仅在类层次结构中的一些类中有意义,而在其他类中没有意义时,你可将该行为抽取到单独的访问者类中, 只需实现接收相关类的对象作为参数的访问者方法并将其他方法留空即可。
访问者模式实现步骤
1.提供一个抽象访问者类:声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的抽象方法
2.提供一个具体访问者类:实现抽象访问者角色所声明的抽象方法,也就是抽象访问者所声明的各个访问操作
3.提供一个抽象被访问者类:声明一个接受操作,接受一个访问者对象作为一个变量的抽象方法
4.提供一个或多个被访问者类:被访问者的抽象方法的具体实现
5.提供一个结构对象类:可以遍历结构中的所有元素;如果有需要,可提供访问元素接口,元素可设计存储到容器中
//不同人逛公园
//莫影: 看美女
//美女: 看风景
//情侣: 约会
#include <iostream>
#include <list>
#include <string>
using namespace std;
class ParkElement;
class Visitor {
public:
virtual void Visit(ParkElement* park) = 0;
};
class ParkElement {
public:
virtual void Accept(Visitor* visitor) = 0;
string GetAddr() { return addr; };
protected:
string addr;
};
//小树林
class Grove : public ParkElement {
public:
Grove() { this->addr = "小树林"; }
void Accept(Visitor* visitor) { visitor->Visit(this); }
};
class Lake : public ParkElement {
public:
Lake() { this->addr = "湖边"; }
void Accept(Visitor* visitor) { visitor->Visit(this); }
};
//集中管理
class Park : public ParkElement {
public:
Park() { parkList.clear(); }
void SetPart(ParkElement* parkElement) { parkList.push_back(parkElement); }
void Accept(Visitor* visitor) {
for (auto v : parkList) {
v->Accept(visitor);
}
}
private:
list<ParkElement*> parkList;
};
class Moying : public Visitor {
public:
Moying() : name("莫影") {}
void Visit(ParkElement* park) {
cout << name << " 在 " << park->GetAddr() << " 看美女" << endl;
}
private:
string name;
};
class MM : public Visitor {
public:
MM() : name("美女") {}
void Visit(ParkElement* park) {
cout << name << " 在 " << park->GetAddr() << " 欣赏风景" << endl;
}
private:
string name;
};
class Lovers : public Visitor {
public:
Lovers() : name("情侣") {}
void Visit(ParkElement* park) {
cout << name << " 在 " << park->GetAddr() << " 约会" << endl;
}
private:
string name;
};
int main() {
//创建访问者
Moying* pMy = new Moying;
MM* pMM = new MM;
Lovers* pLove = new Lovers;
//创建被访问者
Grove* pGrove = new Grove;
Lake* pLake = new Lake;
pLake->Accept(pMy);
pGrove->Accept(pMM);
pGrove->Accept(pLove);
cout << "----------------------------" << endl;
Park* p = new Park;
p->SetPart(pLake);
p->SetPart(pGrove);
p->Accept(pMy);
p->Accept(pMM);
p->Accept(pLove);
return 0;
}
访问者模式优缺点
优点
-
开闭原则: 你可以引入在不同类对象上执行的新行为, 且无需对这些类做出修改
-
单一职责原则: 可将同一行为的不同版本移到同一个类中
-
访问者对象可以在与各种对象交互时收集一些有用的信息
缺点
-
每次在元素层次结构中添加或移除一个类时, 你都要更新所有的访问者
-
在访问者同某个元素进行交互时, 它们可能没有访问元素私有成员变量和方法的必要权限