当前位置: 首页 > news >正文

访问者模式

在这里插入图片描述
图片转载自

#include<iostream>
using namespace std;
#include<list>
/*模板工厂单例化,所有的商品被注册进工厂中*/
/*访问者模式(行为型模式)
访问者,被访问者
visit   accept
让访问变成一种操作,不同的访问操作有具体的实现,但是无需修改源代码(准确点说,是无需修改被访问者的源代码)
只需要增加新的具体访问类即可。局部的符合开闭原则,只是访问者类需要进行扩展和少量修改
在vitst方法中以被访问者作为参数,方法体是被访问者调用accept方法
*/
class Apple;
class Book;class Vistor
{
public:void set_name(std::string name){_name = name;}virtual void visit(Apple* apple) = 0;virtual void visit(Book* book) = 0;
protected:std::string _name;//观察者的名字
};class Customer :public Vistor
{void visit(Apple* apple){cout << "顾客" << _name << "挑选苹果" << endl;}void visit(Book* book){cout << "顾客" << _name << "买书"<<endl;}
};class Saler :public Vistor
{void visit(Apple* apple){cout << "收银员" << _name << "称苹果" << endl;}void visit(Book* book){cout << "收银员" << _name << "计算书价" << endl;}
};class Product
{
public:virtual void accept(Vistor* vistor) = 0;
};class Apple :public Product
{
public:void accept(Vistor* vistor)override{vistor->visit(this);}
};class Book :public Product
{
public:void accept(Vistor* vistor)override//在具体的被访问者类中的accept方法,参数都是访问者的父类{vistor->visit(this);}
};class ShoppingCart//管理者,可以增加或删除商品
{
public:void accept(Vistor* vistor){for (auto prd : _prd_list)prd->accept(vistor);}void addProduct(Product* product){_prd_list.push_back(product);}void removeProduct(Product* product){_prd_list.remove(product);}
private:std::list<Product*> _prd_list;
};int main()
{Book book;Apple apple;ShoppingCart basket;basket.addProduct(&book);basket.addProduct(&apple);Customer customer1;customer1.set_name("小明");basket.accept(&customer1);Saler saler;saler.set_name("小米");basket.accept(&saler);return 0;
}

这个示例代码写得一般,重点理解上面那张图:访问者模式就是在新增一个visitor类,visitor的visit方法定义参数为物品的抽象父类,同时在accepter中增加accept方法,accept方法参数为visitor,这样当具体访问者,调用其visit方法,方法体为accepter.accept()。

可以看到在保证accepter的数据结构不发生变化的情况下(没有新增或者删除),可以非常方便增加新的一种访问方法,只需要新增加一个访问类即可,但是如果我们数据结构发生变化之后,就需要修改继承自Visitor类的所有类了,这也违背了开闭原则,因此我们应该认真考虑,到底我们的数据结构是定死的还是经常变化的。没有任何一种设计模式是十全十美的,总是有所取舍,有所利弊,根据实际情况来选择才是最好的设计方法。

http://www.lryc.cn/news/167659.html

相关文章:

  • epoll 的实现
  • 怎么用excel管理固定资产
  • 记录crack某IDE插件过程
  • Android DEX相关,ART加载OAT文件
  • laravel框架 - 安装初步使用学习 composer安装
  • API实战教程:使用身份证OCR识别API构建一个应用
  • 前端-layui动态渲染表格行列与复杂表头合并
  • IDM(Internet Download Manager)下载器2024最新版本如何下载?
  • 前端综合练手小项目
  • 接口优化1
  • 【无公网IP内网穿透】 搭建Emby媒体库服务器并远程访问「家庭私人影院」
  • QML android 采集手机传感器数据 并通过udp 发送
  • stableDiffusion安装
  • QT基础教程(QPushButton及信号与槽)
  • Android 实战项目分享(一)用Android Studio绘制贝塞尔曲线的艺术之旅
  • Windows系统关机后自动重启的解决方法
  • 微服务如何改变软件开发:实战经验与最佳实践分享
  • 安装深度(Deepin)系统
  • Leetcode: 645.错误的集合 题解【超详细】
  • 闲鱼自动化软件——筛选/发送系统 V22已经测试完毕
  • 数学建模__动态规划
  • 【IoT】生产制造:锅仔片上机做 SMT 加工吗?
  • Stable Diffusion代码简介
  • 操作系统的运行机制
  • 分布式事务解决方案之2PC
  • 发现某设备 adb shell ps 没有输出完整信息
  • qt模拟鼠标事件
  • Linux运维基础知识大全
  • 西门子S7-1200F或1500F系列安全PLC的组态步骤和基础编程(一)
  • 负载均衡-ribbon源码解析