网站首页 > 博客文章 正文
在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的更改,将会给子类带来很繁重的变更负担,甚至破坏原有设计。那么如何在不更改类层次结构的前提下,在运行时根据需要透明地为类层次结构上的各个子类动态添加新的操作,从而避免上述问题呢?
这就要用到我们今天要讲的访问者模式了,访问者模式即表示一个作用于某对象结构中的个元素的操作。使得可以在不改变各元素的类的前提下定义(扩展)作用于这些元素的新操作(变化)。
UML图:
- 抽象访问者(Visitor)角色:声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。
- 具体访问者(ConcreteVisitor)角色:实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。
- 抽象节点(Element)角色:声明一个接受操作,接受一个访问者对象作为一个参量。
- 具体节点(ConcreteElement)角色:实现了抽象元素所规定的接受操作。
- 结构对象(ObiectStructure)角色:有如下的一些责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如列(List)或集合(Set)。
举个例子,假设我们现在做了一个企业员工信息管理系统,我们已经把每个员工的基本信息都存起来了,现在我们想要快速的比较每一个员工的某项信息的差别,比如年龄、籍贯、学历、收入等等。
代码实现:
#include <iostream>
#include <string>
#include <list>
using namespace std;
class Element;
class Visitor
{
public:
virtual void Visit(Element *element) {};
};
// "Element"
class Element
{
public:
// Methods
virtual void Accept(Visitor *visitor) {};
};
// "ConcreteElement"
class Employee : public Element
{
public:
string name; //姓名
int age; //年龄
string hometown; //籍贯
string education; //学历
double income; //工资
public:
Employee(string name, int age, string hometown, string education, double income) {
this->name = name;
this->age = age;
this->hometown = hometown;
this->education = education;
this->income = income;
}
void Accept(Visitor *visitor) {
visitor->Visit(this);
}
};
class AgeVisitor : public Visitor
{
public:
void Visit(Element *element) {
Employee *employee = ((Employee*)element);
cout << employee->name << "的年龄为: " << employee->age << endl;
}
};
class EducationVisitor : public Visitor
{
public:
void Visit(Element *element) {
Employee *employee = ((Employee*)element);
cout << employee->name << "的学历为: " << employee->education << endl;
}
};
class IncomeVisitor : public Visitor
{
public:
void Visit(Element *element) {
Employee *employee = ((Employee*)element);
cout << employee->name << "的工资为: " << employee->income << endl;
}
};
// "ObjectStructure"
class Employees
{
private:
list< Employee*> employees;
public:
void Attach(Employee *employee)
{
employees.push_back(employee);
}
void Detach(Employee *employee)
{
employees.remove(employee);
}
void Accept(Visitor *visitor)
{
for (std::list<Employee*>::iterator it = employees.begin(); it != employees.end(); ++it)
(*it)->Accept(visitor);
}
};
void main()
{
Employees *e = new Employees();
e->Attach(new Employee("张三", 25, "南京", "博士", 25000.0));
e->Attach(new Employee("李四", 28, "上海", "硕士", 18000.0));
e->Attach(new Employee("赵五", 27, "杭州", "本科", 15000.0));
// 创建访问者
IncomeVisitor *v1 = new IncomeVisitor();
AgeVisitor *v2 = new AgeVisitor();
EducationVisitor *v3 = new EducationVisitor();
// 访问员工信息
e->Accept(v1);
e->Accept(v2);
e->Accept(v3);
}
运行结果:
张三的工资为: 25000
李四的工资为: 18000
赵五的工资为: 15000
张三的年龄为: 25
李四的年龄为: 28
赵五的年龄为: 27
张三的学历为: 博士
李四的学历为: 硕士
赵五的学历为: 本科
猜你喜欢
- 2024-10-01 设计模式——备忘录模式(备忘录界面设计)
- 2024-10-01 设计模式 之 行为型模式(行为型设计模式特点)
- 2024-10-01 Go语言设计模式-访问者(go语言有设计模式吗)
- 2024-10-01 Spring Boot 实战:运用访问者模式灵活扩展订单处理逻辑
- 2024-10-01 visitor pattern 访问者模式(访问者模式工作原理)
- 2024-10-01 Aha!设计模式(105)-访问者模式(1)
- 2024-10-01 GOF设计模式(命令模式,访问者模式,迭代器模式,观察者模式)
- 2024-10-01 设计模式第2招第9式之解释器模式(解释器原理)
- 2024-10-01 设计模式第2招第1式之观察者模式(观察者设计模式的优点)
- 2024-10-01 「编程设计」访问者(Visitor)模式-补丁式为原体系增加新功能
你 发表评论:
欢迎- 07-07Xiaomi Enters SUV Market with YU7 Launch, Targeting Tesla with Bold Pricing and High-Tech Features
- 07-07Black Sesame Maps Expansion Into Robotics With New Edge AI Strategy
- 07-07Wuhan's 'Black Tech' Powers China's Cross-Border Push with Niche Electronics and Scientific Firepower
- 07-07Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!
- 07-07IT运维必会的30个工具(it运维工具软件)
- 07-07开源项目有你需要的吗?(开源项目什么意思)
- 07-07自动化测试早就跑起来了,为什么测试管理还像在走路?
- 07-07Cursor 最强竞争对手来了,专治复杂大项目,免费一个月
- 最近发表
-
- Xiaomi Enters SUV Market with YU7 Launch, Targeting Tesla with Bold Pricing and High-Tech Features
- Black Sesame Maps Expansion Into Robotics With New Edge AI Strategy
- Wuhan's 'Black Tech' Powers China's Cross-Border Push with Niche Electronics and Scientific Firepower
- Maven 干货 全篇共:28232 字。预计阅读时间:110 分钟。建议收藏!
- IT运维必会的30个工具(it运维工具软件)
- 开源项目有你需要的吗?(开源项目什么意思)
- 自动化测试早就跑起来了,为什么测试管理还像在走路?
- Cursor 最强竞争对手来了,专治复杂大项目,免费一个月
- Cursor 太贵?这套「Cline+OpenRouter+Deepseek+Trae」组合拳更香
- 为什么没人真的用好RAG,坑都在哪里? 谈谈RAG技术架构的演进方向
- 标签列表
-
- ifneq (61)
- 字符串长度在线 (61)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)