《C++新经典设计模式》之第20章 访问者模式

《C++新经典设计模式》之第20章 访问者模式

        • 访问者模式.cpp

访问者模式.cpp
#include <iostream>
#include <list>
#include <memory>
using namespace std;

// 提供一个作用于某对象结构中的各元素的操作表示,便可以在不改变各元素类的前提下定义(扩展)作用于这些元素的新操作
// 允许一个或多个操作应用于一组对象上,使对象本身和操作解耦
// 5种角色
// Visitor(抽象访问者),为对象结构中的元素声明访问接口
// ConcreteVisitor(具体访问者),实现接口
// Element(抽象元素),定义Accept方法,形参通常为Visitor指针
// ConcreteElement(具体元素),实现Accept方法,该方法中调用ConcreteVisitor的访问操作,实现元素操作
// ObjectStructure(对象结构),元素集合,存放元素对象并提供遍历其内部元素的接口,一般用于同一批元素的相同操作

namespace ns1
{
    class Medicine // 药品父类
    {
    public:
        virtual ~Medicine() {}
        virtual string getMdcName() const = 0; // 药品名称
        virtual float getPrice() const = 0;    // 药品总价格,单位:元
    };

    class M_asplcrp : public Medicine // 药品:阿司匹林肠溶片
    {
    public:
        string getMdcName() const override
        {
            return "Aspirin enteric-coated tablets";
        }
        float getPrice() const override
        {
            return 46.8f; // 为简化代码,直接给出药品总价而不单独强调药品数量了,比如该药品医生给开了两盒,一盒是23.4,那么这里直接返回两盒的价格
        }
    };

    class M_fftdnhsp : public Medicine // 药品:氟伐他汀钠缓释片
    {
    public:
        string getMdcName() const override
        {
            return "Fluvastatin sodium sustained-release tablets";
        }
        float getPrice() const override
        {
            return 111.3f; // 三盒的价格
        }
    };

    class M_dlx : public Medicine // 药品:黛力新
    {
    public:
        string getMdcName() const override
        {
            return "Deanxit";
        }
        float getPrice() const override
        {
            return 122.0f; // 两盒的价格
        }
    };

    class MedicineProc // 针对药品的处理相关类
    {
        list<shared_ptr<Medicine>> m_mdclist; // 药品列表,记录着药品单上的所有药品
    public:
        // 增加药品到药品列表中
        void addMedicine(const shared_ptr<Medicine> &p_mdc) { m_mdclist.push_back(p_mdc); }

        // 针对费用缴纳和取药所做的处理动作
        void procAction(const string &strvisitor) // strvisitor代表拿到了药品单的人,不同的人拿到药品单所要做的处理也不同
        {
            if (strvisitor == "Toll collector") // 收费人员要根据药品单向我(患者)收取费用
            {
                float totalcost = 0.0f; // 总费用
                for (auto iter = m_mdclist.begin(); iter != m_mdclist.end(); ++iter)
                {
                    float tmpprice = (*iter)->getPrice();
                    totalcost += tmpprice;

                    cout << "yao: " << (*iter)->getMdcName() << ", price: " << tmpprice << endl;
                }
                cout << "total price: " << totalcost << ", Toll collector charges a fee!" << endl;
            }
            else if (strvisitor == "Drug taking personnel") // 取药人员要根据药品单为我拿药
                for (auto iter = m_mdclist.begin(); iter != m_mdclist.end(); ++iter)
                    cout << "Drug taking personnel give " << (*iter)->getMdcName() << " to me!" << endl;
            else if (strvisitor == "dietitian")
                cout << "Nutritionist suggested: match coarse grains with staple foods and eat meat properly!" << endl;
            else if (strvisitor == "Fitness coach")
                cout << "The fitness coach suggested: do more aerobic exercises such as jogging (35 minutes), warm up before and after jogging, avoid anxiety, avoid staying up late, and take a bed rest before 22:30!" << endl;
        }
    };
}

namespace ns2
{
    class Visitor; // 类前向声明
    class Medicine // 药品父类
    {
    public:
        virtual ~Medicine() {}
        virtual void Accept(shared_ptr<Visitor> &pvisitor) = 0; // 这里的形参是访问者父类指针
    public:
        virtual string getMdcName() = 0; // 药品名称
        virtual float getPrice() = 0;    // 药品总价格,单位:元
    };

    class M_asplcrp : public Medicine // 药品:阿司匹林肠溶片
    {
    public:
        string getMdcName() override { return "Aspirin enteric-coated tablets"; }
        float getPrice() override { return 46.8f; }

    public:
        void Accept(shared_ptr<Visitor> &pvisitor) override;
    };

    class M_fftdnhsp : public Medicine // 药品:氟伐他汀钠缓释片
    {
    public:
        string getMdcName() override { return "Fluvastatin sodium sustained-release tablets"; }
        float getPrice() override { return 111.3f; }

    public:
        void Accept(shared_ptr<Visitor> &pvisitor) override;
    };

    class M_dlx : public Medicine // 药品:黛力新
    {
    public:
        string getMdcName() override { return "Deanxit"; }
        float getPrice() override { return 122.0f; }

    public:
        void Accept(shared_ptr<Visitor> &pvisitor) override;
    };

    class Visitor // 访问者父类
    {
    public:
        virtual ~Visitor() {}

        virtual void Visit_elm_asplcrp(M_asplcrp *pelem) = 0;   // 访问元素:阿司匹林肠溶片
        virtual void Visit_elm_fftdnhsp(M_fftdnhsp *pelem) = 0; // 访问元素:氟伐他汀钠缓释片
        virtual void Visit_elm_dlx(M_dlx *pelem) = 0;           // 访问元素:黛力新

        以下几个接口的名字都叫Visit(成员函数重载)
        // virtual void Visit(M_asplcrp* pelem) = 0;   //访问元素:阿司匹林肠溶片
        // virtual void Visit(M_fftdnhsp* pelem) = 0;  //访问元素:氟伐他汀钠缓释片
        // virtual void Visit(M_dlx* pelem) = 0;       //访问元素:黛力新
    };

    class Visitor_SFRY : public Visitor // 收费人员访问者子类
    {
        float m_totalcost = 0.0f; // 总费用
    public:
        void Visit_elm_asplcrp(M_asplcrp *pelem) override
        {
            float tmpprice = pelem->getPrice();
            cout << "yao: " << pelem->getMdcName() << ", price: " << tmpprice << endl;
            m_totalcost += tmpprice;
        }
        void Visit_elm_fftdnhsp(M_fftdnhsp *pelem) override
        {
            float tmpprice = pelem->getPrice();
            cout << "yao: " << pelem->getMdcName() << ", price: " << tmpprice << endl;
            m_totalcost += tmpprice;
        }
        void Visit_elm_dlx(M_dlx *pelem) override
        {
            float tmpprice = pelem->getPrice();
            cout << "yao: " << pelem->getMdcName() << ", price: " << tmpprice << endl;
            m_totalcost += tmpprice;
        }

        // 返回总费用
        float getTotalCost() const { return m_totalcost; }
    };

    class Visitor_QYRY : public Visitor // 取药人员访问者子类
    {
    public:
        void Visit_elm_asplcrp(M_asplcrp *pelem) override
        {
            cout << "Drug taking personnel give " << pelem->getMdcName() << " to me!" << endl;
        }
        void Visit_elm_fftdnhsp(M_fftdnhsp *pelem) override
        {
            cout << "Drug taking personnel give " << pelem->getMdcName() << " to me!" << endl;
        }
        void Visit_elm_dlx(M_dlx *pelem) override
        {
            cout << "Drug taking personnel give " << pelem->getMdcName() << " to me!" << endl;
        }
    };

    class Visitor_YYS : public Visitor // 营养师访问者子类
    {
    public:
        void Visit_elm_asplcrp(M_asplcrp *pelem) override
        {
            cout << "The nutritionist suggested: Eating more coarse grains and less oil can effectively prevent blood clots!" << endl;
        }
        void Visit_elm_fftdnhsp(M_fftdnhsp *pelem) override
        {
            cout << "The nutritionist suggested: Eating more mushrooms, onions, and kiwifruit can effectively reduce blood lipids!" << endl;
        }
        void Visit_elm_dlx(M_dlx *pelem) override
        {
            cout << "The nutritionist suggested: Go out more to breathe fresh air, get more sunshine, go to more crowded places, and keep an optimistic and cheerful mood!" << endl;
        }
    };

    // 各个药品子类Accept方法的实现体代码
    void M_asplcrp::Accept(shared_ptr<Visitor> &pvisitor)
    {
        pvisitor->Visit_elm_asplcrp(this);
    }
    void M_fftdnhsp::Accept(shared_ptr<Visitor> &pvisitor)
    {
        pvisitor->Visit_elm_fftdnhsp(this);
    }
    void M_dlx::Accept(shared_ptr<Visitor> &pvisitor)
    {
        pvisitor->Visit_elm_dlx(this);
    }

    class ObjectStructure // 对象结构
    {
        list<shared_ptr<Medicine>> m_mdclist; // 药品列表
    public:
        // 增加药品到药品列表中
        void addMedicine(const shared_ptr<Medicine> &p_mdc)
        {
            m_mdclist.push_back(p_mdc);
        }

        void procAction(shared_ptr<Visitor> &pvisitor)
        {
            for (auto iter = m_mdclist.begin(); iter != m_mdclist.end(); ++iter)
                (*iter)->Accept(pvisitor);
        }
    };
}

namespace ns3
{
    class Medicine; // 类前向声明
    class Visitor   // 访问者父类
    {
    public:
        virtual ~Visitor() {}
        virtual void Visit(Medicine *const pelem) = 0;
    };

    class Medicine // 药品父类
    {
    public:
        virtual ~Medicine() {}
        virtual void Accept(shared_ptr<Visitor> &pvisitor) { pvisitor->Visit(this); }

    public:
        virtual string getMdcName() const = 0; // 药品名称
        virtual float getPrice() const = 0;    // 药品总价格,单位:元
    };

    class M_asplcrp : public Medicine // 药品:阿司匹林肠溶片
    {
    public:
        string getMdcName() const override { return "Aspirin enteric-coated tablets"; }
        float getPrice() const override { return 46.8f; }
    };

    class M_fftdnhsp : public Medicine // 药品:氟伐他汀钠缓释片
    {
    public:
        string getMdcName() const override { return "Fluvastatin sodium sustained-release tablets"; }
        float getPrice() const override { return 111.3f; }
    };

    class M_dlx : public Medicine // 药品:黛力新
    {
    public:
        string getMdcName() const override { return "Deanxit"; }
        float getPrice() const override { return 122.0f; }
    };

    class Visitor_SFRY : public Visitor // 收费人员访问者子类
    {
        float m_totalcost = 0.0f; // 总费用
    public:
        void Visit(Medicine *const m) override
        {
            float tmpprice = m->getPrice();
            m_totalcost += tmpprice;

            cout << "yao: " << m->getMdcName() << ", price: " << tmpprice << endl;
        }

        float getTotalCost() const { return m_totalcost; } // 返回总费用
    };

    class Visitor_QYRY : public Visitor // 取药人员访问者子类
    {
    public:
        void Visit(Medicine *const m) override
        {
            cout << "Drug taking personnel give " << m->getMdcName() << " to me!" << endl;
        }
    };

    class Visitor_YYS : public Visitor // 营养师访问者子类
    {
    public:
        void Visit(Medicine *const m) override
        {
            cout << "The nutritionist suggested: Eating more coarse grains and less oil can effectively prevent blood clots!" << endl;
            cout << "The nutritionist suggested: Eating more mushrooms, onions, and kiwifruit can effectively reduce blood lipids!" << endl;
            cout << "The nutritionist suggested: Go out more to breathe fresh air, get more sunshine, go to more crowded places, and keep an optimistic and cheerful mood!" << endl;
        }
    };

    class ObjectStructure // 对象结构
    {
        list<shared_ptr<Medicine>> m_mdclist; // 药品列表
    public:
        // 增加药品到药品列表中
        void addMedicine(const shared_ptr<Medicine> &p_mdc)
        {
            m_mdclist.push_back(p_mdc);
        }

        void procAction(shared_ptr<Visitor> &pvisitor)
        {
            for (auto iter = m_mdclist.begin(); iter != m_mdclist.end(); ++iter)
                (*iter)->Accept(pvisitor);
        }
    };
}

int main()
{
#if 0
    using namespace ns1;
    shared_ptr<Medicine> pm1(new M_asplcrp());  // 药品阿司匹林肠溶片
    shared_ptr<Medicine> pm2(new M_fftdnhsp()); // 药品氟伐他汀钠缓释片
    shared_ptr<Medicine> pm3(new M_dlx());      // 药品黛力新

    MedicineProc mdcprocobj;
    mdcprocobj.addMedicine(pm1);
    mdcprocobj.addMedicine(pm2);
    mdcprocobj.addMedicine(pm3);
    mdcprocobj.procAction("Toll collector");
    mdcprocobj.procAction("Drug taking personnel");
#endif

#if 1
    // using namespace ns2;
    using namespace ns3;
    shared_ptr<Medicine> mdc_asplcrp(new M_asplcrp());
    shared_ptr<Medicine> mdc_fftdnhsp(new M_fftdnhsp());
    shared_ptr<Medicine> mdc_dlx(new M_dlx());

    // 各个元素子类调用Accept接受访问者的访问,就可以实现访问者要实现的功能
    shared_ptr<Visitor> visitor_sf(new Visitor_SFRY()); // 收费人员访问者子类,里面承载着向我(患者)收费的算法
    mdc_asplcrp->Accept(visitor_sf);                    // 累加“阿司匹林肠溶片”的价格
    mdc_fftdnhsp->Accept(visitor_sf);                   // 累加“氟伐他汀钠缓释片”的价格
    mdc_dlx->Accept(visitor_sf);                        // 累加“黛力新”的价格
    cout << "total price: " << dynamic_pointer_cast<Visitor_SFRY>(visitor_sf)->getTotalCost() << ", the toll collector charged me!" << endl;

    shared_ptr<Visitor> visitor_qy(new Visitor_QYRY()); // 取药人员访问者子类,里面承载着向我发放药品的算法
    mdc_asplcrp->Accept(visitor_qy);                    // 我取得“阿司匹林肠溶片”
    mdc_fftdnhsp->Accept(visitor_qy);                   // 我取得“氟伐他汀钠缓释片”
    mdc_dlx->Accept(visitor_qy);                        // 我取得“黛力新”

    shared_ptr<Visitor> visitor_yys(new Visitor_YYS()); // 营养师访问者子类,里面承载着为我配置营养餐的算法
    mdc_asplcrp->Accept(visitor_yys);                   // 营养师针对治疗预防血栓药“阿司匹林肠溶片”给出的对应的营养餐建议
    mdc_fftdnhsp->Accept(visitor_yys);                  // 营养师针对降血脂药“氟伐他汀钠缓释片”给出的对应的营养餐建议
    mdc_dlx->Accept(visitor_yys);                       // 营养师针对治疗神经紊乱药“黛力新”给出的对应的营养餐建议

    shared_ptr<ObjectStructure> objstruc(new ObjectStructure());
    objstruc->addMedicine(mdc_asplcrp);
    objstruc->addMedicine(mdc_fftdnhsp);
    objstruc->addMedicine(mdc_dlx);
    objstruc->procAction(visitor_yys); // 将一个访问者对象(visitor_yys)应用到一批元素上,以实现对一批元素进行同一种(营养方面的)操作
#endif

    cout << "Over!\n";
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/229298.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue 核心 数据监听 computed | watch

Vue 核心 数据监听 computed | watch 一、今日学习目标 1.指令补充 指令修饰符v-bind对样式增强的操作v-model应用于其他表单元素 2.computed计算属性 基础语法计算属性vs方法计算属性的完整写法成绩案例 3.watch侦听器 基础写法完整写法 4.综合案例 &#xff08;演示&…

视频剪辑:视频转码实用技巧,批量将MP4转为MP3音频

随着数字媒体设备的普及&#xff0c;视频和音频文件已成为日常生活中的重要组成部分。有时&#xff0c;可能要将MP4视频文件转换为MP3音频文件&#xff0c;以提取其中的音频内容或者进行其他处理。这是耗费时间的任务&#xff0c;那要如何操作呢&#xff1f;本文详解云炫AI智剪…

使用pytorch查看中间层特征矩阵以及卷积核参数

这篇是我对哔哩哔哩up主 霹雳吧啦Wz 的视频的文字版学习笔记 感谢他对知识的分享 1和4是之前讲过的alexnet和resnet模型 2是分析中间层特征矩阵的脚本 3是查看卷积核参数的脚本 1设置预处理方法 和图像训练的时候用的预处理方法保持一致 2实例化模型 3载入之前的模型参数 4载入…

C#网络编程(System.Net命名空间)

目录 一、System.Net命名空间 1.Dns类 &#xff08;1&#xff09;示例源码 &#xff08;2&#xff09;生成效果 2.IPAddress类 &#xff08;1&#xff09;示例源码 &#xff08;2&#xff09;生成效果 3.IPEndPoint类 &#xff08;1&#xff09; 示例源码 &#xff0…

计算机方向的一些重要缩写和简介

参考&#xff1a; 深度学习四大类网络模型 干货|机器学习超全综述&#xff01; 机器学习ML、卷积神经网络CNN、循环神经网络RNN、马尔可夫蒙特卡罗MCMC、生成对抗网络GAN、图神经网络GNN——人工智能经典算法 MLP&#xff08;Multi Layer Perseption&#xff09;用在神经网络中…

Conda常用命令总结

使用conda或anaconda的小伙伴们都知道&#xff0c;图形界面时不靠谱的&#xff0c;而在命令行下&#xff0c;所有的操作就会稳定很多&#xff0c;且极少出现问题。因此&#xff0c;熟记conda的命令行就变得十分有用。但对于我这样近50岁依旧奋斗在代码第一线的大龄程序员而已&a…

作业12.8

1. 使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数。将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是…

HarmonyOS Developer——鸿蒙【构建第一个JS应用(FA模型)】

创建JS工程 JS工程目录结构 构建第一个页面 构建第二个页面 实现页面间的跳转 使用真机运行应用 说明 为确保运行效果&#xff0c;本文以使用DevEco Studio 3.1 Release版本为例&#xff0c;点击此处获取下载链接。 创建JS工程 若首次打开DevEco Studio&#xff0c;请点击…

C# Solidworks二次开发:选择管理器相关的API介绍

今天在讲述主要内容之前&#xff0c;先说一个不太相关的问题。 我之前在其他文章中看到有一些朋友在问为什么获取到的点位数据需要乘以1000进行单位转换&#xff0c;其实原因是这样的&#xff0c;在所有使用的API中如果没有特殊说明&#xff0c;所有的长度单位都是米&#xff…

解读链上经济“一等公民”:加密AI代理的优势和前沿应用

机器人正在成为加密经济的“一等公民”&#xff0c;最近的案例就能印证这一趋势。 搜索者&#xff08;Searchers&#xff09;部署像Jaredfromsubway.eth这样的机器人&#xff0c;利用真人用户对便利的渴望在DEX抢先交易。Banana Gun和Maestro允许真人用户通过Telegram的便利进…

网络编程基础api

1. IP 协议 1.1 IP 分片 &#xff08;1&#xff09;IP 分片和重组主要依靠 IP 头部三个字段&#xff1a;数据报标识、标志和片偏移 以太网帧的 MTU 是 1500 字节&#xff1b; 一个每个分片都有自己的 IP 头部&#xff0c;它们都具有相同的标识值&#xff0c;有不同的片偏移…

MVC、MVP、MVVM模式的区别

前言&#xff1a;这三个表现层框架设计模式是依次进化而形成MVC—>MVP—>MVVM。在以前传统的开发模式当中即MVC模式&#xff0c;前端人员只负责Model&#xff08;数据库&#xff09;、 View&#xff08;视图&#xff09;和 Controller /Presenter/ViewModel&#xff08;控…

【SQL开发实战技巧】系列(四十八):Oracle12C常用新特性☞多分区操作和管理

系列文章目录 【SQL开发实战技巧】系列&#xff08;一&#xff09;:关于SQL不得不说的那些事 【SQL开发实战技巧】系列&#xff08;二&#xff09;&#xff1a;简单单表查询 【SQL开发实战技巧】系列&#xff08;三&#xff09;&#xff1a;SQL排序的那些事 【SQL开发实战技巧…

总线(什么是南北桥?您都用过哪些总线?)

什么是总线&#xff1f; 计算机系统中的总线&#xff08;Bus&#xff09;是指计算机设备和设备之间传输信息的公共数据通道&#xff0c;是连接计算机硬件系统内多种设备的通信线路&#xff0c;它的一个重要特征是由总线上的所有设备共享&#xff0c;因此可以将计算机系统内的多…

ky10 x86 一键安装wvp gb28181 pro平台

下载代码 git clone https://gitcode.net/zengliguang/ky10_x86_wvp_record_offline_install.gitfinalshell mobaxterm 修改服务器ip 查看服务器ip ip a 在脚本文件中修改服务器ip 执行安装脚本 切换到root用户 sudo su cd ky10_x86_wvp_record_of

Qt12.8

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为…

代码随想录算法训练营 --- 第五十九天

今天同样是单调栈&#xff0c;第二题很重要。 第一题&#xff1a; 简介&#xff1a; 本题可以说和上一题很是相似&#xff0c;只是有一点不同&#xff0c;数组是循环的。本题有两种巧妙地解法&#xff0c;都不难。 第一种方法&#xff08;也是第一个想出来的方法&#xff09…

会个postman面试就要15k,怎么敢的啊!

postman应用实战 下面以微信公众平台举例&#xff1a; 第一步、先创建文件夹 第二步、打开postman&#xff0c;创建collections 第三步、设置环境变量&#xff0c;全局变量 设置环境变量&#xff1b;如下图&#xff1a; 设置全局变量&#xff1b;如下图&#xff1a; 第四步、…

机器人阻抗控制直观(图示理解)与控制框架/架构

在刚性碰撞下&#xff0c;机器人的阻抗调节可以使其更好地适应外部环境。具体来说&#xff0c;通过建立力与位移之间的关系&#xff0c;并改变阻抗参数&#xff0c;可以控制机器人对外部力的响应。 在具体实现上&#xff0c;可以采用基于位置的阻抗控制或基于力的阻抗控制。基于…

机器学习---集成学习的初步理解

1. 集成学习 集成学习(ensemble learning)是现在非常火爆的机器学习方法。它本身不是一个单独的机器学 习算法&#xff0c;而是通过构建并结合多个机器学习器来完成学习任务。也就是我们常说的“博采众长”。集 成学习可以用于分类问题集成&#xff0c;回归问题集成&#xff…
最新文章