【C++】设计模式全解析——访问者模式(code c++)


访问者模式

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。 这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

  • 意图: 主要将数据结构与数据操作分离。
  • 主要解决: 稳定的数据结构和易变的操作耦合问题。
  • 何时使用: 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。
  • 如何解决: 在被访问的类里面加一个对外提供接待访问者的接口。
  • 关键代码: 在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。
  • 应用实例: 我们去银行柜台办业务,一般情况下会开几个个人业务柜台的,你去其中任何一个柜台办理都是可以的。我们的访问者模式可以很好付诸在这个场景中:对于银行柜台来说,他们是不用变化的,就是说今天和明天提供个人业务的柜台是不需要有变化的。而我们作为访问者,今天来银行可能是取消费用流水,明天来银行可能是去办理手机银行业务,这些是我们访问者的操作,一直是在变化的。
  • 优点: 1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。
  • 缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。
  • 使用场景: 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。
  • 注意事项: 访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

程序代码

访问者模式实现 code c++

#include <iostream>
using namespace std;

class A;
class B;
class C;
class D;
class E;

class Base {
public :
    class IVisitor {
    public :
        virtual void visit(A *) = 0;
        virtual void visit(B *) = 0;
        virtual void visit(C *) = 0;
        virtual void visit(D *) = 0;
        virtual void visit(E *) = 0;

    };
    virtual void say() = 0;
    virtual void accept(IVisitor *) = 0; 
    virtual ~Base() {}
};

class A : public Base {
public :
    void say() override {
        cout << "Class A" << endl;
    }
    void accept(IVisitor *vis) override {
        vis->visit(this); // 匹配数据操作类中的重载函数
        return ;
    }
};

class B : public Base {
public :
    void say() override {
        cout << "Class B" << endl;
    }
    void accept(IVisitor *vis) override {
        vis->visit(this);
        return ;
    }
};

class C : public Base {
public :
    void say() override {
        cout << "Class C" << endl;
    }
    void accept(IVisitor *vis) override {
        vis->visit(this);
        return ;
    }
};

class D : public Base {
public :
    void say() override {
        cout << "Class D" << endl;
    }
    void accept(IVisitor *vis) override {
        vis->visit(this);
        return ;
    }
};

class E : public Base {
public :
    void say() override {
        cout << "Class E" << endl;
    }
    void accept(IVisitor *vis) override {
        vis->visit(this);
        return ;
    }
};

class calcVisitor : public Base::IVisitor { // 数据操作类 
public :
    calcVisitor(int &x) : x(x) {}
    void visit(A *obj) override {
        x *= 2;
    }
    void visit(B *obj) override {
        x -= 3;
    }
    void visit(C *obj) override {
        x += 6;
    }
    void visit(D *obj) override {
        x /= 3;
    }
    void visit(E *obj) override {
        x -= 2;
    }
private:
    int &x;
};

int main() { // 访问者模式实现, 类型->功能(补充知识: 解决新增功能维护难——通过让编译器提示改代码)
    srand(time(0));
    Base *p[5] = {nullptr};
    for (int i = 0; i < 5; ++i) { // 第一次类指针类型转换
        switch (rand() % 5) {
            case 0: p[i] = new A(); break;
            case 1: p[i] = new B(); break;
            case 2: p[i] = new C(); break;
            case 3: p[i] = new D(); break;
            case 4: p[i] = new E(); break;    
        }
    } 
    int x = 1;
    calcVisitor vis(x);
    for (int i = 0, pre = x; i < 5; ++i) {
        p[i]->accept(&vis); // 第二次类指针类型转换
        p[i]->say();
        cout << pre << " -> " << x << endl;
        pre = x;
    }
    return 0;
}

输出结果

Class A
1 -> 2
Class E
2 -> 0
Class C
0 -> 6
Class D
6 -> 2
Class B
2 -> -1

结论

代码示例,有问题留言。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

idiot5liev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值