c++设计模式概述之访问者
代码写的不够规范,目的是为了缩短篇幅,实际中请注意。
参看: http://c.biancheng.net/view/1397.html
1、概述
类比生活中的场景,购物商场中的商品、顾客、收营员。商品针对不同的人员,对商品的操作也是不同的。比如,顾客挑选商品,购买商品, 而收银员则是核对商品价格,针对商品收银。 同样是商品,但是面对不同的人,其操作也是不同的。
访问者模式包含以下主要角色:
A、抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。
B、具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
C、抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
D、具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
E、对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现
下面以商场购物为例
2、抽象访问者类
// 顾客,抽象类
class visitor
{
public:
void set_name(std::string name) { _str_name = name; } // 访问商品
virtual void visit(bowel *pbowel) = 0;
virtual void visit(chicken *pchicken) = 0;
std::string get_name() { return _str_name; };
protected:
std::string _str_name;
};
3、抽象商品类
// 抽象商品类
class product
{
public:
virtual void accept(visitor *pvisitor) = 0;
};
4、具体产品类
这里准备了碗和鸡肉两种商品
// 碗,一个具体的商品类
class bowel : public product
{
public:
void accept(visitor *pvisitor)
{
if (pvisitor)
pvisitor->visit(this);
}
}; // 鸡肉,一个具体的商品类
class chicken : public product
{
public:
void accept(visitor *pvisitor)
{
if (pvisitor)
pvisitor->visit(this);
}
};
5、具体的访问者
这里实现了顾客和收银员
// 顾客A
class customerA : public visitor
{
public:
void visit(bowel *pbowel)
{
if (pbowel)
std::cout << _str_name << "正在挑选-碗\n";
} void visit(chicken *pchicken)
{
if (pchicken)
std::cout << _str_name << "正在挑选-鸡肉\n";
}
}; //收银员
class saler : public visitor
{
public:
void visit(bowel *pbowel)
{
if (pbowel)
std::cout << _str_name << "正在扫描商品-碗\n";
} void visit(chicken *pchicken)
{
if (pchicken)
std::cout << _str_name << "正在扫描商品-鸡肉\n";
}
};
6、对象结构类
这里以购物车为例
// 购物车, 对象结构
class shopping_cart
{
public:
// 可以添加商品到购物车
void add(product *ppd)
{
if (ppd)
{
_list_product.push_back(ppd);
std::cout << "\n购物车:添加商品成功\n";
}
} // 可以从购物车删除商品
void remove(product* ppd)
{
// 1、要删除的商品不存在
if (!ppd)
{
std::cout << "\n购物车:商品删除失败,待删除的商品不存在\n";
return;
} // 2、找下,购物车是否存在该商品
std::list<product*> ::iterator& it = std::find(_list_product.begin(), _list_product.end(), ppd);
// 找到了,再删除
if (_list_product.end() != it)
{
_list_product.remove(ppd);
std::cout << "\n购物车:成功移除商品\n";
}
else
std::cout << "\n购物车:删除商品失败,没有找到该商品\n";
} void accept(visitor *pvisitor)
{
if (!pvisitor)
return; for each(auto item in _list_product)
{
item->accept(pvisitor);
}
} private:
// 购物车,可以存放很多商品,
std::list<product*> _list_product;
};
7、调用
void call_visitor()
{
// 1、商场准备上架商品
bowel bw1;
bowel bw2; chicken ck1;
chicken ck2; // 2、再给客户准备购物车,方便购物
shopping_cart sc; // 消费者A + 商场服务对象
customerA customa;
customa.set_name(std::string("顾客A"));
saler salerZ;
salerZ.set_name(std::string("收银员Z")); // 3、顾客挑选商品
// 3.1、顾客需要购物车
sc.accept(&customa);
// 3.2、将选好的商品放入购物车
std::cout << "\n---------------------------------\n";
customa.visit(&bw1);
sc.add(&bw1); std::cout << "\n---------------------------------\n";
customa.visit(&bw2);
sc.add(&bw2); std::cout << "\n---------------------------------\n";
sc.add(&ck1);
customa.visit(&ck1); std::cout << "\n---------------------------------\n";
sc.add(&ck2);
customa.visit(&ck2);
std::cout << "\n---------------------------------\n"; // 4、商品买多了? 移除
std::cout << customa.get_name() << "\n正在移除商品\n";
sc.remove(&ck2); std::cout << "\n-------------------------\n选购结束,准备结算:\n";
// 5、这时,购物车是由收银员check
sc.accept(&salerZ);
}
8、结果

c++设计模式概述之访问者的更多相关文章
- 设计模式 ( 二十 ) 访问者模式Visitor(对象行为型)
设计模式 ( 二十 ) 访问者模式Visitor(对象行为型) 1.概述 在软件开发过程中,对于系统中的某些对象,它们存储在同一个集合collection中,且具有不同的类型,而且对于该集合中的对象, ...
- OOAD-设计模式(二)之GRASP模式与GOF设计模式概述
一.GRASP模式(通用责任分配软件模式)概述 1.1.理解责任 1)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为.数据.对象的创建等 知道责任——表示知道什么 行为责任 ...
- PHP设计模式概述
PHP设计模式概述 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. ...
- java设计模式概述
java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式. 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模 ...
- 23种GoF设计模式概述
23种GoF设计模式概述 在前面,我们对 GoF 的 23 种设计模式进行了分类,这里先对各个设计模式的功能进行简要介绍,以便有个大概了解.后面的章节再进行详细介绍. 创建型模式 关注于怎么创建对象的 ...
- Java设计模式(一):设计模式概述、UML图、设计原则
1 设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中. 1977年美国著名建筑大师.加利福尼亚大学伯克利分校环境结构 ...
- 设计模式(一)----设计模式概述及UML图解析
1.设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中. 1977年美国著名建筑大师.加利福尼亚大学伯克利分校环境结构 ...
- java 28 - 1 设计模式 之 面向对象思想设计原则和模版设计模式概述
在之前的java 23 中,了解过设计模式的单例模式和工厂模式.在这里,介绍下设计模式 面向对象思想设计原则 在实际的开发中,我们要想更深入的了解面向对象思想,就必须熟悉前人总结过的面向对象的思想的设 ...
- 重学 Java 设计模式:实战访问者模式「模拟家长与校长,对学生和老师的不同视角信息的访问场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 能力,是你前行的最大保障 年龄会不断的增长,但是什么才能让你不 ...
随机推荐
- JSOI2021 游记
Day 0 - 2021.4.9 写一波最近的事情吧( 3 月 20 号出头 cnblogs 抽风,说 25 号恢复来着,我就囤了一堆博客在本地准备 25 号发,结果到时候就懒得动了.干脆越屯越多,省 ...
- intent.getSerializableExtra(转)
Activity之间通过Intent传递值,支持基本数据类型和String对象及它们的数组对象byte.byte[].char.char[].boolean.boolean[].short.short ...
- 【R】行或列数目不同的两个数据框如何用rbind/cbind合并?
目录 前言 方法一:dplyr的bind_rows 方法二:plyr的rbind.fill 前言 通常我们用rbind和cbind合并相同行列的数据框.当两个数据框具有不同行列数目时,直接用会报错. ...
- 【GS模型】全基因组选择之rrBLUP
目录 1. 理论 2. 实操 2.1 rrBLUP包简介 2.2 实操 3. 补充说明 关于模型 关于交叉验证 参考资料 1. 理论 rrBLUP是基因组选择最常用的模型之一,也是间接法模型的代表.回 ...
- Nginx 动态增加扩展
Nginx 动态增加扩展 1. 先查看目前nginx已加载模块 /home/nginx-1.18.0 # nginx -V nginx version: nginx/1.18.0 built by g ...
- jenkins原理简析
持续集成Continuous Integration(CI) 原理图: Gitlab作为git server.Gitlab的功能和Github差不多,但是是开源的,可以用来搭建私有git server ...
- 34. Swap Nodes in Pairs
Swap Nodes in Pairs My Submissions QuestionEditorial Solution Total Accepted: 95230 Total Submission ...
- k8s集群中部署Rook-Ceph高可用集群
先决条件 为确保您有一个准备就绪的 Kubernetes 集群Rook,您可以按照这些说明进行操作. 为了配置 Ceph 存储集群,至少需要以下本地存储选项之一: 原始设备(无分区或格式化文件系统) ...
- C++中Try Catch中的继承
1.C++中Try Catch简介:我们编译运行程序出错的时候,编译器就会抛出异常.抛出异常要比终止程序灵活许多. 而C++异常是指在程序运行时发生的反常行为,这些行为超出了函数正常功能的范围.当程序 ...
- 16. Linux find查找文件及文件夹命令
find的主要用来查找文件,查找文件的用法我们比较熟悉,也可用它来查找文件夹,用法跟查找文件类似,只要在最后面指明查找的文件类型 -type d,如果不指定type类型,会将包含查找内容的文件和文件夹 ...