天天看点

行为变化模式之Visitor(访问器模式) | C++

一、学前思考

1.去银行办理业务得时候任意一个窗口都能办理业务

2.实际上就是将数据结构和数据操作解耦

3.这个模式用得比较少,水至清则无鱼(条件太苛刻),但是一旦用上整个结构都会被visitor模式所绑架。

二、行为变化模式之Visitor(访问器模式)

原始问题代码:

class Visitor;
class Element
{
public:
    virtual void Func1()=0;
    virtual ~Element(){};
    //#以上是已有得操作(暗含已经开发完成并且部署分发之后),当需要有一个新的操作Func2()时
    virtual void Func2(int date)=0;
};

class ElementA : public Element
{
    public:
    void Func1() override{
        //...
    }
    //#新添加
    void Func2(int date) override{
        //...
    }
};
    
class ElementB : public Element
{
    public:
    void Func1() override{
        //***
    }
    //#新添加
    void Func2(int date) override{
        //...
    }
};
    
//违背开闭原则
           

1.动机

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

访问器模式就是要解决如何在不更改类层次结构得前提下,在运行时根据需要透明底为类层次结构上得各个类结构动态添加新的操作。

2.模式定义

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

理解:这里的不改变指的是编译时不改变。已有的元素是固定的,但是使用的方法不同。如果子类个数(意思子类必须稳定)不确定那么这个模式就没法使用。

解决存在问题的代码:

#include <iostream>
using namespace std;
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(){}
};
//以上是已有得操作(暗含已经开发完成并且部署分发之后),当有一个新的需求变更时如下
class Visitor1 : public Visitor{
    public:
    void visitElementA(ElementA& element) override{
        cout<<"Visitor1 is processing ElementA"<<endl;
    }
    void visitElementB(ElementB& element) override{
        cout<<"Visitor1 is processing ElementB"<<endl;
    }
};
//再次出现新的需求
class Visitor2 : public Visitor{
    public:
    void visitElementA(ElementA& element) override{
        cout<<"Visitor2 is processing ElementA"<<endl;
    }
    void visitElementB(ElementB& element) override{
        cout<<"Visitor2 is processing ElementB"<<endl;
    }
};
//主函数调用
int main()
{
    Visitor2 visitor;
    ElementB element;
    element.accept(visitor);//double dispatch,多态的二次辨析
    
}
           

3.要点总结

  • Visitor模式通过所谓双重分发(double dispatch)来实现在不更改((编译时)不添加新的操作)Element类层次结构的前提下,在运行时透明地位类层次结构上的各个类动态添加新的操作(支持变化)。
  • 双重分发即Visitor模式中包括了两个多态分发(注意其中的多态机制):第一个位accept方法的多态辨析;第二个位visitElementX方法的多态辨析。
  • Visitor模式的最大缺点在于扩展类层次结构(添加新的Element子类),会导致 Visitor了的改变。因此Visitor模式适用于”Element类层次稳定,而其中的操作却经常面临频繁改动“
  • 软件中有稳定的有变化的部分,设计模式就是解决变化的部分。如果极端情况下,比如全是稳定的,或者全是变化的,设计模式没有变法解决这样的问题。

4.结构

行为变化模式之Visitor(访问器模式) | C++

继续阅读