访问者模式 行为型设计模式之九

1.定义

在不改变数据结构的前提下,增加作用于一组对象元素的新功能。

2.动机

  1. 访问者模式适用于数据结构相对稳定的系统
  2. 它把数据结构和作用于数据结构之上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。
  3. 访问者模式的目的是要把处理从数据结构分离出来。如果这样的系统有比较稳定的数据结构,又有已与变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得更容易。反之亦然。

一句话总结就是,访问者不会改变原有系统的数据结构,而只是使用原有系统的数据去实现自己的功能。这个实现的功能可以自己定制,但是原有系统需要留出这样的访问者应用接口。

3.示例代码

一台电脑中有很多组件,CPU、GPU、硬盘。维修人员对电脑进行整体维修时,需要对各部件依次进行维修,而且每部件具体的维修方式不同。不同的维修人员对相同的部件维修方式可能也不同。维修人员就是访问者。访问者类中实现了针对不同部件的维修方式。电脑就是被访问者。被访问者提供访问接口,使用访问者类中实现的不同部件维修方式,对内部部件进行访问。

cpp 复制代码
#include <iostream>
#include <list>
using namespace std;

class Visitor;

//组成Computer的各组件基类
class Element
{
public:
    Element(string strName) :m_strName(strName) {}
    string GetName()
    {
        return m_strName;
    }
    //组件接受访问者访问的接口
    virtual void AcceptVisitor(Visitor* pVisitor) = 0;

private:
    //组件的标识名称
    string m_strName;
};

//访问者基类,针对不同组件,提供不同的访问接口
class Visitor
{
public:
    virtual void VisitCPU(Element* pEle) = 0;
    virtual void VisitGPU(Element* pEle) = 0;
    virtual void VisitDISK(Element* pEle) = 0;
};

//Computer类,由各组件组成,访问者访问Computer时将依次访问各组件
class Computer
{
public:
    ~Computer()
    {
        for (Element* pElement : m_listEle)
        {
            delete pElement;
        }
    }

    void AddElement(Element* pEle)
    {
        m_listEle.push_back(pEle);
    }

    void DelElement(Element* pEle)
    {
        m_listEle.remove(pEle);
    }

    //访问者访问Computer时将依次访问各组件
    void AcceptVisitor(Visitor* pVisitor)
    {
        for (Element* pElement : m_listEle)
        {
            pElement->AcceptVisitor(pVisitor);
        }
    }

private:
    list<Element*> m_listEle;
};

//访问者实现类,实现各自的访问方法
class VisitorA : public Visitor
{
public:
    void VisitCPU(Element* pEle)
    {
        printf("Visitor A record CPU's name:%s\n", pEle->GetName().c_str());
    }

    void VisitGPU(Element* pEle)
    {
        printf("Visitor A do nothing to GPU:%s\n", pEle->GetName().c_str());
    }

    void VisitDISK(Element* pEle)
    {
        printf("Visitor A change DISK:%s\n", pEle->GetName().c_str());
    }
};

class VisitorB : public Visitor
{
public:
    void VisitCPU(Element* pEle)
    {
        printf("Visitor B do nothing to CPU:%s\n", pEle->GetName().c_str());
    }

    void VisitGPU(Element* pEle)
    {
        printf("Visitor B record GPU's name:%s\n", pEle->GetName().c_str());
    }

    void VisitDISK(Element* pEle)
    {
        printf("Visitor B do nothing to DISK:%s\n", pEle->GetName().c_str());
    }
};

//组件的实现类,调用访问者相应的访问方法
class CPU :public Element
{
public:
    CPU(string strName) :Element(strName) {}
    void AcceptVisitor(Visitor* pVisitor)
    {
        pVisitor->VisitCPU(this);
    }
};

class GPU :public Element
{
public:
    GPU(string strName) :Element(strName) {}
    void AcceptVisitor(Visitor* pVisitor)
    {
        pVisitor->VisitGPU(this);
    }
};

class Disk :public Element
{
public:
    Disk(string strName) :Element(strName) {}
    void AcceptVisitor(Visitor* pVisitor)
    {
        pVisitor->VisitDISK(this);
    }
};

int main()
{
    Computer oComputer;
    oComputer.AddElement(new CPU("i9-10980XE"));
    oComputer.AddElement(new GPU("Titan RTX"));
    oComputer.AddElement(new Disk("HOF PRO M.2"));

    VisitorA oVisitorA;
    VisitorB oVisitorB;

    oComputer.AcceptVisitor(&oVisitorA);
    oComputer.AcceptVisitor(&oVisitorB);

    return 0;
}

4.组成结构

  1. Visitor 是抽象访问者,为该对象结构中的 ConcreteElement 的每一个类声明一个 visit 操作
  2. ConcreteVisitor :是一个具体的访问值 实现每个有 Visitor 声明的操作,是每个操作实现的部分.
  3. ObjectStructure :能枚举它的元素, 可以提供一个高层的接口,用来允许访问者访问元素
  4. Element: 定义一个 accept 方法,接收一个访问者对象
  5. ConcreteElement: 为具体元素,实现了 accept 方法

5.引用

C++设计模式------访问者模式 - 冰糖葫芦很乖 - 博客园 (cnblogs.com)

相关推荐
知识领航员13 小时前
蘑兔AI音乐深度实测:功能拆解、实测表现与适用场景
java·c语言·c++·人工智能·python·算法·github
jf加菲猫14 小时前
第21章 Qt WebEngine
开发语言·c++·qt·ui
码农-阿杰15 小时前
深入理解 synchronized 底层实现:从 HotSpot C++ 源码看对象锁与 Monitor 机制
开发语言·c++·
Szime15 小时前
深智微IC华润微代理:MCU选型与工业控制方案推荐
c++
geovindu16 小时前
go: Lock/Mutex Pattern
开发语言·后端·设计模式·golang·互斥锁模式
叼烟扛炮16 小时前
C++ 知识点18 内部类
开发语言·c++·算法·内部类
汉克老师16 小时前
GESP5级C++考试语法知识(十五、分治算法(二))
c++·算法·排序算法·分治算法·gesp5级·gesp五级
汉克老师16 小时前
GESP6级C++考试语法知识(五、格雷码)
c++·算法·位运算·异或·gesp6级·gesp六级·格雷码
学习中.........17 小时前
常见设计模式
java·设计模式
程序leo源17 小时前
C语言知识总结
c语言·开发语言·c++·经验分享·笔记·青少年编程·c#