您的位置:首页 > 游戏 > 手游 > 卡盟平台官网_四川手机响应式网站建设推荐_西安网络科技公司排名_线上销售平台都有哪些

卡盟平台官网_四川手机响应式网站建设推荐_西安网络科技公司排名_线上销售平台都有哪些

2025/2/24 14:41:50 来源:https://blog.csdn.net/zg260/article/details/145532320  浏览:    关键词:卡盟平台官网_四川手机响应式网站建设推荐_西安网络科技公司排名_线上销售平台都有哪些
卡盟平台官网_四川手机响应式网站建设推荐_西安网络科技公司排名_线上销售平台都有哪些

一:概述

        访问者模式将作用于对象层次结构的操作封装为一个对象,并使其能够在不修改对象层次结构的情况下定义新的操作。

        《设计模式:可复用面向对象软件的基础》一书中的访问者模式因两个原因而具有传奇色彩:一是因为它的复杂性,二是因为它使用了一种名为“双重分派”的技术。双重分派指的是根据对象和函数参数选择成员函数的过程。当然,访问者模式的复杂性主要在于 C++ 本身不支持双重分派。在讨论单分派和双重分派之前,让我先谈谈访问者模式。

       什么是“双重分派”?双重分派(Double Dispatch)是一个动态选择调用方法的机制,其中被调用的具体函数依赖于两个对象的运行时类型,而不仅仅是一个对象的类型。这在多态编程中尤其有用,能够实现复杂的行为决策。在 C++ 中,双重分派通常通过虚函数和函数重载的组合实现,例如在访问者模式中。

二:使用场景

        1. 操作应该在对象层次结构上执行。

         2. 操作变更频繁。

         3. 对象层次结构是稳定的。 

三:类结构设计

        

  • Visitor 类:在对象结构上定义访问操作(visit 方法),用来描述对象结构中各元素可能执行的行为。

  • ConcreteVisitor 类:实现 Visitor 接口中的具体访问操作,为不同的元素提供特定的处理逻辑。

  • Element 类:表示对象结构中的元素,定义了 accept 方法,用于接收 Visitor 的操作请求。

  • ConcreteElement 类:具体的对象结构元素,实现 accept 方法,将自己作为参数传递给访问者,以完成双向的操作绑定。

四:一个具体的例子

        

      访问者模式有两种类型的层次结构:对象层次结构(CarElement)和操作层次结构(CarElementVisitor)。对象层次结构相对稳定,但操作层次结构可能需要支持新操作。CarElement 和 CarElementVisitor 都充当接口,这意味着每个具体的汽车元素(如 Wheel、Engine、Body 和 Car)都必须实现 accept(CarElementVisitor) 成员函数。相应地,每个具体的操作(如 CarElementDoVisitor 和 CarElementPrintVisitor)都必须实现四个重载的 visit(Wheel)visit(Engine)visit(Body)visit(Car) 方法。

      假设操作 CarElementPrintVisitor 被应用于对象层次结构。CarElementPrintVisitor 的任务可能是打印被访问的汽车零部件的名称。首先,像 Engine 这样的汽车元素接受访问者(accept(CarElementVisitor)),并使用访问者通过 visitor.visit(this) 调用操作层次结构,将自身作为参数传递。这确保了调用 CarElementPrintVisitor 上的 visit(Engine) 重载。访问 Car 是特殊的,因为 Car 由多个汽车元素组成。因此,Caraccept 成员函数将接受调用委托给它的所有汽车零部件。

     关于访问者的一个关键特征是:它依赖于两个对象,决定执行什么操作:访问者和被访问的对象。

五:代码示例

#include <iostream>
#include <string>
#include <vector>// 前向声明 Visitor 和元素类
class CarElementVisitor;class CarElement {
public:// 接受访问者操作的接口,由具体元素实现virtual void accept(CarElementVisitor& visitor) const = 0;virtual ~CarElement() = default;
};// 前向声明具体元素类
class Body;
class Car;
class Engine;
class Wheel;// 访问者接口,定义了针对不同元素的访问操作
class CarElementVisitor {
public:// 针对不同具体元素的访问操作的虚函数virtual void visit(Body body) const = 0;virtual void visit(Car car) const = 0;virtual void visit(Engine engine) const = 0;virtual void visit(Wheel wheel) const = 0;virtual ~CarElementVisitor() = default;
};// 轮胎类,表示汽车的一个轮胎
class Wheel : public CarElement {
public:// 构造函数,接收轮胎的名称Wheel(const std::string& n) : name(n) { }// 接受访问者,调用访问者的 visit(Wheel) 方法void accept(CarElementVisitor& visitor) const override {visitor.visit(*this);}// 获取轮胎的名称std::string getName() const {return name;}
private:std::string name; // 轮胎名称
};// 车身类,表示汽车的车身
class Body : public CarElement {
public:// 接受访问者,调用访问者的 visit(Body) 方法void accept(CarElementVisitor& visitor) const override {visitor.visit(*this);}
};// 发动机类,表示汽车的发动机
class Engine : public CarElement {
public:// 接受访问者,调用访问者的 visit(Engine) 方法void accept(CarElementVisitor& visitor) const override {visitor.visit(*this);}
};// 汽车类,表示一辆汽车,由多个汽车元素组成
class Car : public CarElement {
public:// 构造函数,接收一个汽车元素列表Car(std::initializer_list<CarElement*> carElements) : elements{ carElements } {}// 接受访问者,依次让每个汽车元素接受访问void accept(CarElementVisitor& visitor) const override {for (auto elem : elements) {elem->accept(visitor); // 委托访问操作给子元素}visitor.visit(*this); // 最后访问汽车本身}
private:std::vector<CarElement*> elements; // 汽车元素列表
};// 执行动作的访问者类,定义具体的访问行为
class CarElementDoVisitor : public CarE

六:相关设计模式 

  • 稳定的对象层次结构通常会应用 组合模式(Composite Pattern)
  • 迭代器模式(Iterator Pattern) 通常用于遍历对象层次结构。
  • 新的元素可以通过创建型模式(例如 工厂方法(Factory Method)原型模式(Prototype Pattern))来创建

七:优缺点

优点:

  • 可以轻松地向操作层次结构中添加新的操作(访问者)。
  • 一个操作可以被封装在一个访问者中。
  • 在遍历对象层次结构时,可以构建和维护状态。

缺点:

  • 如果需要在对象层次结构中添加新的被访问对象(VisitedObject),修改会非常困难。
  • 需要将新的被访问对象(VisitedObject)添加或从对象层次结构中移除。
  • 需要扩展访问者的接口,并在每个具体访问者中添加或移除 visit(VisitedObject) 成员函数。


八:参考:

1. The Visitor Pattern – MC++ BLOG
2. https://commons.wikimedia.org/w/index.php?curid=122709059

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com