目录

行为变化_Visitor


状态变化模式

在组件的构建过程中,组件行为的变化经常导致组件本身剧烈的变化。“行为变化“模式将组件的行为和组件本身进行解耦,从而支持组件行为的变化,实现两者之间的松耦合。

典型模式

  • Command
  • Visitor

1 Visitor

1.1 模式动机

在软件构建过程中,由于需求的改变,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的更改,将会给子类带来很繁重的变更负担,甚至破坏原有设计。

如何在不更改类层次结构的前提下,在运行时根据需要透明地为类层次结构上的各个类动态添加新的操作,从而避免上述问题?

1.2 模式定义

表示一个作用于某对象结构中的各元素的操作。使得可以在不改变(稳定)各元素的类的前提下定义(扩展)作用于这些元素的新操作(变化)。

1.3 模式示例代码

# include <iostream>
# include <string>

// 前向声明
class Car;
class SedanCar;
class SUVCar;

// 抽象访问者类:汽车访问者
class CarVisitor {
public:
    virtual void visit(Car* car) = 0;
    virtual void visit(SedanCar* sedanCar) = 0;
    virtual void visit(SUVCar* suvCar) = 0;
};

// 抽象元素类:汽车
class Car {
public:
    virtual void accept(CarVisitor* visitor) = 0;
};

// 具体元素类:轿车
class SedanCar : public Car {
public:
    void accept(CarVisitor* visitor) {
        visitor->visit(this);
    }

    std::string getSedanCarInfo() {
        return "这是一辆轿车";
    }
};

// 具体元素类:SUV
class SUVCar : public Car {
public:
    void accept(CarVisitor* visitor) {
        visitor->visit(this);
    }

    std::string getSUVCarInfo() {
        return "这是一辆SUV";
    }
};

// 具体访问者类:汽车信息访问者
class CarInfoVisitor : public CarVisitor {
public:
    void visit(Car* car) {
        std::cout << "访问了一辆未知类型的汽车" << std::endl;
    }

    void visit(SedanCar* sedanCar) {
        std::cout << "访问了一辆轿车:" << sedanCar->getSedanCarInfo() << std::endl;
    }

    void visit(SUVCar* suvCar) {
        std::cout << "访问了一辆SUV:" << suvCar->getSUVCarInfo() << std::endl;
    }
};

int main() {
    // 创建汽车信息访问者
    CarInfoVisitor visitor;

    // 创建轿车对象并访问
    Car* sedanCar = new SedanCar();
    sedanCar->accept(&visitor);

    // 创建SUV对象并访问
    Car* suvCar = new SUVCar();
    suvCar->accept(&visitor);

    // 释放内存(可选)
    delete sedanCar;
    delete suvCar;

    return 0;
}

2 要点总结

Visitor 模式通过所谓双重分发(double dispatch)来实现在不更改 (不添加新的操作-编译时)Element 类层次结构的前提下,在运行时透明地为类层次结构上的各个类动态添加新的操作(支持变化)

所谓双重分发即 Visitor 模式中间包括了两个多态分发(注意其中的多态机制):第一个为 accept 方法的多态辨析;第二个为 yisitElementX 方法的多态辨析。

Visitor 模式的最大缺点在于扩展类层次结构(增添新的 Element 子类),会导致 Visitor 类的改变。因此 Vistor 模式适用于“Element 类层次结构稳定,而其中的操作却经常面临频繁改动“。