网站建设服务费税率多少,汕头模板建站流程,广东住房和城乡建设厅网站王芃,装饰设计师在哪个平台上寻找1.概述 访问者模式是一种行为设计模式#xff0c; 它能将算法与其所作用的对象隔离开来。 访问者模式主要解决的是数据与算法的耦合问题#xff0c;尤其是在数据结构比较稳定#xff0c;而算法多变的情况下。为了不污染数据本身#xff0c;访问者会将多种算法独立归档…1.概述 访问者模式是一种行为设计模式 它能将算法与其所作用的对象隔离开来。 访问者模式主要解决的是数据与算法的耦合问题尤其是在数据结构比较稳定而算法多变的情况下。为了不污染数据本身访问者会将多种算法独立归档并在访问数据时根据数据类型自动切换到对应的算法实现数据的自动响应机制并确保算法的自由扩展。 访问者模式在实际开发中使用的非常少因为它比较难以实现并且应用该模式肯能会导致代码的可读性变差可维护性变差在没有特别必要的情况下不建议使用访问者模式。 2.结构
访问者模式结构包括以下几个要素
抽象访问者Visitor角色可以是接口或者抽象类定义了一系列操作方法用来处理所有数据元素通常为同名的访问方法并以数据元素类作为入参来确定那个重载方法被调用。具体访问者ConcreteVisitor角色访问者接口的实现类可以有多个实现每个访问者都需要实现所有数据元素类型的访问重载方法。抽象元素Element角色被访问的数据元素接口定义了一个接受访问者的方法 accept 其意义是指每一个元素都要可以被访问者访问。具体元素ConcreteElement角色 具体数据元素实现类提供接受访问方法的具体实现而这个具体的实现通常情况下是使用访问者提供的访问该元素类的方法其accept实现方法中调用访问者并将自己 this 传回。客户端 ( Client ) : 使用容器并初始化其中各类数据元素并选择合适的访问者处理容器中的所有数据对象。 3.实现
3.1 实例类比 假如有这样一位非常希望赢得新客户的资深保险代理人。 他可以拜访街区中的每栋楼 尝试向每个路人推销保险。 所以 根据大楼内组织类型的不同 他可以提供专门的保单
如果建筑是居民楼 他会推销医疗保险。如果建筑是银行 他会推销失窃保险。 3.2 实例引入 访问者模式可以被用于实现 KPI关键绩效指标考核系统。在这个场景下你可以将员工、团队等作为对象结构的元素而不同的 KPI 考核指标如工作绩效、创新能力、团队协作等作为不同的访问者。这样你就可以灵活地添加新的考核指标而无需修改对象结构中的元素类。
3.3 结构分析
在这个案例中代码中的各个结构可以对应到策略模式中的不同角色
抽象访问者Visitor角色对应代码Visitor接口用于处理所有员工数据元素。具体访问者ConcreteVisitor角色对应代码KPIVisitor访问者具体实现。抽象元素Element角色对应代码Employee定义了一个接受访问者的方法 accept 便于每一个元素都要可以被访问者访问。具体元素ConcreteElement角色对应代码Manager、Engineer 具体员工数据元素实现类提供接受访问方法的具体实现通常情况下accept实现方法中调用访问者并将自己 this 传回。
类图如下
3.4 具体实现
#include iostream
#include string
using namespace std;
// 元素接口员工
// 访问者接口KPI 考核
class Visitor;
class Engineer;
class Manager;class Employee {
public:virtual void accept(Visitor* visitor) 0;
};class Visitor {
public:virtual void visit(Engineer* engineer) 0;virtual void visit(Manager* manager) 0;
};// 具体元素类工程师
class Engineer :public Employee {public:void accept(Visitor* visitor) {visitor-visit(this);}// 工程师的特有方法void doCoding() {std::cout 工程师正在编码... endl;}
};// 具体元素类项目经理
class Manager :public Employee {public:void accept(Visitor* visitor) {visitor-visit(this);}// 经理的特有方法void manageTeam() {std::cout 经理正在管理团队... endl;}
};// 具体访问者类KPI 考核实现
class KPIVisitor :public Visitor {public:void visit(Engineer *engineer) {std::cout 工程师的工作绩效考核中... endl;engineer-doCoding(); // 工程师的特有工作}void visit(Manager* manager) {std::cout 项目经理的工作绩效考核中... endl;manager-manageTeam(); // 经理的特有工作}
};// 客户端测试int main() {Employee *engineer new Engineer();Employee *manager new Manager();Visitor *kpiVisitor new KPIVisitor();// 对工程师进行 KPI 考核engineer-accept(kpiVisitor);// 对经理进行 KPI 考核manager-accept(kpiVisitor);return 0;
}3.5 运行结果 4.访问者模式优缺点
优点
扩展性好。在不修改对象结构中的元素的情况下为对象结构中的元素添加新的功能。复用性好。通过访问者来定义整个对象结构通用的功能从而提高复用程度。分离无关行为。通过访问者来分离无关的行为把相关的行为封装在一起构成一个访问者这样每一个访问者的功能都比较单一。
缺点
对象结构变化很困难。在访问者模式中每增加一个新的元素类都要在每一个具体访问者类中增加相应的具体操作这违背了“开闭原则”。违反了依赖倒置原则。访问者模式依赖了具体类而没有依赖抽象类。违反了单一职责原则。访问者模式将相关操作集中到访问者类中可能导致该类承担过多的责任违反单一职责原则。违反了开放封闭原则。如果系统中新增了一个元素类所有的具体访问者类都需要修改不符合开闭原则。
5.应用场景
当对象的数据结构相对稳定而操作却经常变化的时候。比如编译器的语法树分析编译器可以使用访问者模式来遍历语法树对不同类型的节点执行不同的操作。需要将数据结构与不常用的操作进行分离的时候。比如扫描文件内容这个动作通常不是文件常用的操作但是对于文件夹和文件来说和数据结构本身没有太大关系树形结构的遍历操作扫描是一个额外的动作如果给每个文件都添加一个扫描操作会太过于重复这时采用访问者模式是非常合适的能够很好分离文件自身的遍历操作和外部的扫描操作。需要在运行时动态决定使用哪些对象和方法的时候。比如对于监控系统来说很多时候需要监控运行时的程序状态但大多数时候又无法预知对象编译时的状态和参数这时使用访问者模式就可以动态增加监控行为。