C++设计模式:访问者模式

访问者模式

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

使用场景

对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。

需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。

优缺点

优点:

1、符合单一职责原则。

2、优秀的扩展性。

3、灵活性。

缺点:

1、具体元素对访问者公布细节,违反了迪米特原则。

2、具体元素变更比较困难。

3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

注意事项

访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。

UML结构图

代码实现

father.h
创建抽象类 - 访问者、计算机部件

#include <iostream>
using namespace std;

class Computer;
class Mouse;
class Keyboard;
class Monitor;

class ComputerPartVisitor   //基类-访问者
{
public:
    ComputerPartVisitor() {}
    virtual ~ComputerPartVisitor() {}

    virtual void visit(Computer *computer) = 0;
    virtual void visit(Mouse *mouse) = 0;
    virtual void visit(Keyboard *keyboard) = 0;
    virtual void visit(Monitor *monitor) = 0;
};

class ComputerPart  //基类-计算机部件
{
public:
    ComputerPart() {}
    virtual ~ComputerPart() {}

    virtual void accept(ComputerPartVisitor *computerPartVisitor) = 0;
    virtual string getString() = 0;
};

son.h
创建实体类 - 键盘、鼠标、显示屏、计算机、计算机访问者
实现主要功能:计算机访问者中可以根据访问对象的不同,执行不同对象的操作

#include "father.h"
#include <vector>
#include <string>

class Keyboard: public ComputerPart //子类-键盘
{
public:
    void accept(ComputerPartVisitor *computerPartVisitor)
    {
        computerPartVisitor->visit(this);
    }

    string getString() { return "Displaying Keyboard"; }
};

class Monitor: public ComputerPart  //子类-显示器
{
public:
    void accept(ComputerPartVisitor *computerPartVisitor)
    {
        computerPartVisitor->visit(this);
    }

    string getString() { return "Displaying Monitor"; }
};

class Mouse: public ComputerPart    //子类-鼠标
{
public:
    void accept(ComputerPartVisitor *computerPartVisitor)
    {
        computerPartVisitor->visit(this);
    }

    string getString() { return "Displaying Mouse"; }
};

class Computer: public ComputerPart //子类-计算机(包含显示器、鼠标、键盘)
{
public:
    Computer()
    {
        ComputerPart *keyboard = new Keyboard();
        ComputerPart *monitor = new Monitor();
        ComputerPart *mouse = new Mouse();
        vector.push_back(keyboard);
        vector.push_back(monitor);
        vector.push_back(mouse);
    }

    void accept(ComputerPartVisitor *computerPartVisitor)
    {
        for(size_t i = 0; i < vector.size(); i++)
        {
            vector.at(i)->accept(computerPartVisitor);
        }
        computerPartVisitor->visit(this);
    }

    string getString() { return "Displaying Computer"; }

private:
    std::vector<ComputerPart *> vector;
};

class ComputerPartDisplayVisitor: public ComputerPartVisitor    //子类-计算机访问者
{
public:
    void visit(Computer *computer)
    {
        cout << computer->getString() << endl;
    }

    void visit(Mouse *mouse)
    {
        cout << mouse->getString() << endl;
    }

    void visit(Keyboard *keyboard)
    {
        cout << keyboard->getString() << endl;
    }

    void visit(Monitor *monitor)
    {
        cout << monitor->getString() << endl;
    }
};

main.cpp
实例应用 - 使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分

#include "son.h"

int main()
{
    ComputerPartDisplayVisitor *cp = new ComputerPartDisplayVisitor();
    ComputerPart *computer = new Computer();
    ComputerPart *mouse = new Mouse();
    ComputerPart *keyboard = new Keyboard();
    ComputerPart *monitor = new Monitor();

    computer->accept(cp);
    cout << endl;

    mouse->accept(cp);
    keyboard->accept(cp);
    monitor->accept(cp);

    return 0;
}

运行结果:
Displaying Keyboard
Displaying Monitor
Displaying Mouse
Displaying Computer

Displaying Mouse
Displaying Keyboard
Displaying Monitor

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,C++设计模式,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值