Linux C++ 066-设计模式之访问者模式
本节关键字:Linux、C++、设计模式、访问者模式
相关库函数:
概念
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
访问者模式旨在将数据结构与在该数据结构上执行的操作分离,从而使得添加新的操作变得更容易,而无需修改数据结构本身。解决在稳定数据结构和易变操作之间的耦合问题,使得操作可以独立于数据结构变化。
优缺点
优点
单一职责原则:访问者模式符合单一职责原则,每个类只负责一项职责。
扩展性:容易为数据结构添加新的操作。
灵活性:访问者可以独立于数据结构变化。
缺点
违反迪米特原则:元素需要向访问者公开其内部信息。
元素类难以变更:元素类需要维持与访问者的兼容。
依赖具体类:访问者模式依赖于具体类而不是接口,违反了依赖倒置原则。
使用场景
访问者模式可以用于功能统一,如报表生成、用户界面显示、拦截器和过滤器等。
当需要对一个对象结构中的对象执行多种不同的且不相关的操作时,尤其是这些操作需要避免"污染"对象类本身。
当对象结构稳定,但需要在其上定义多种新操作时,考虑使用访问者模式。
当需要避免操作"污染"对象类时,使用访问者模式封装操作。
角色说明
Visitor 抽象访问者角色:为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。
ConcreteVisitor.具体访问者角色:实现Visitor声明的接口。
Element 定义一个接受访问操作(accept()):它以一个访问者(Visitor)作为参数。
ConcreteElement 具体元素:实现了抽象元素(Element)所定义的接受操作接口。
ObjectStructure 结构对象角色:这是使用访问者模式必备的角色。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。
Client 客户端(可选):使用访问者模式对对象结构进行操作。
示例代码
#include <iostream>
#include <vector>
using namespace std;
class Computer;
class Mouse;
class Keyboard;
class Monitor;
class ComputerPartVisitor
{
public:
ComputerPartVisitor() { }
virtual void visit(Computer *computer) { }
virtual void visit(Mouse *mouse) { }
virtual void visit(Keyboard *keyboard) { }
virtual void visit(Monitor *monitor) { }
};
class ComputerPart
{
public:
ComputerPart() { }
virtual void accept(ComputerPartVisitor *cpv) { }
};
class Keyboard : public ComputerPart
{
public:
Keyboard() { }
void accept(ComputerPartVisitor *cpv) {
cpv->visit(this);
}
};
class Monitor : public ComputerPart
{
public:
void accept(ComputerPartVisitor *cpv) {
cpv->visit(this);
}
};
class Mouse : public ComputerPart
{
public:
void accept(ComputerPartVisitor *cpv) {
cpv->visit(this);
}
};
class Computer : public ComputerPart
{
public:
Computer() {
m_Parts.push_back(new Mouse());
m_Parts.push_back(new Keyboard());
m_Parts.push_back(new Monitor());
}
void accept(ComputerPartVisitor *cpv) {
for (int i = 0; i < m_Parts.size(); i++) {
m_Parts[i]->accept(cpv);
}
cpv->visit(this);
}
private:
vector<ComputerPart*> m_Parts;
};
class ComputerPartDisplayVisitor : public ComputerPartVisitor
{
public:
void visit(Computer *computer) {
cout << "Displaying Computer." << endl;
}
void visit(Mouse *mouse) {
cout << "Displaying Mouse." << endl;
}
void visit(Keyboard *keyboard) {
cout << "Displaying Keyboard." << endl;
}
void visit(Monitor *monitor) {
cout << "Displaying Monitor." << endl;
}
};
int main(int argc, char *argv[])
{
ComputerPart *computer = new Computer();
computer->accept(new ComputerPartDisplayVisitor());
return 0;
}
/*
Displaying Mouse.
Displaying Keyboard.
Displaying Monitor.
Displaying Computer.
*/