Skip to content

Latest commit

 

History

History
122 lines (95 loc) · 2.87 KB

22.访问器模式.md

File metadata and controls

122 lines (95 loc) · 2.87 KB

访问器模式 Visitor

  • 通过双重分发(double dispatch)来实现不更改(不添加新的操作-编译时)Element类层次结构的前提下,在运行时透明的为类层次结构上的各个类动态添加新的操作(支持变化)
  • 最大的缺点在于扩展类层次结构(增添新的Element子类),会导致Visitor类的改变
  • 适用于Element类层次结构稳定,而其中的操作却经常面临频繁改动

动机

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

模式定义

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

代码

原始设计

class Element{
public:
    virtual void Func1() = 0;
+   virtual void Func2(int data) = 0;

    virtual ~Element(){}
};

class ElementA : public Element{
public:
    void Func1() override {
        //...
    }

+    void Func2(int data) override{
+        //...
+    }
};

class ElementB : public Element{
public:
    void Func1() override {
        //...
    }

+    void Func2(int data) override{
+        //...
+    }
};

重构设计

  • 可以预料到类可能需要添加新的操作
  • 写 Visitor 时必须知道 Element 有几个子类
class Visitor;

class Element{
public:
    virtual void accept(Visitor& visitor) = 0;  // 第一次多态辨析

    virtual ~Element(){}
};

class ElementA : public Element{
public:
    void accept(Visitor& visitor) override {
        visitor.visitElementA(*this);
    }
};

class ElementB : public Element{
public:
    void accept(Visitor& visitor) override {
        visitor.visitElementB(*this);           // 第二次多态辨析
    }
};

class Visitor{
public:
    virtual void visitElementA(ElementA& element) = 0;
    virtual void visitElementB(ElementB& element) = 0;

    virtual ~Visitor(){}
};

//=============================================
// 扩展1
class Visitor1 : public Visitor{
public:
    void visitElementA(ElementA& element){
        cout << "Visitor1 is processing ElementA" << endl;
    }
    void visitElementB(ElementB& element){
        cout << "Visitor1 is processing ElementB" << endl;
    }
};
// 扩展2
class Visitor2 : public Visitor{
public:
    void visitElementA(ElementA& element){
        cout << "Visitor2 is processing ElementA" << endl;
    }
    void visitElementB(ElementB& element){
        cout << "Visitor2 is processing ElementB" << endl;
    }
};

int main()
{
    Visitor2 visitor;
    ElementB element;
    element.accept(visitor);    // double dispatch

    return 0;
}

题目