代码写的不够规范,目的是为了缩短篇幅,实际中请注意。

参看: 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++设计模式概述之访问者的更多相关文章

  1. 设计模式 ( 二十 ) 访问者模式Visitor(对象行为型)

    设计模式 ( 二十 ) 访问者模式Visitor(对象行为型) 1.概述 在软件开发过程中,对于系统中的某些对象,它们存储在同一个集合collection中,且具有不同的类型,而且对于该集合中的对象, ...

  2. OOAD-设计模式(二)之GRASP模式与GOF设计模式概述

    一.GRASP模式(通用责任分配软件模式)概述 1.1.理解责任 1)什么是责任 责任是类间的一种合约或义务,也可以理解成一个业务功能,包括行为.数据.对象的创建等 知道责任——表示知道什么 行为责任 ...

  3. PHP设计模式概述

    PHP设计模式概述 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. ...

  4. java设计模式概述

    java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式. 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模 ...

  5. 23种GoF设计模式概述

    23种GoF设计模式概述 在前面,我们对 GoF 的 23 种设计模式进行了分类,这里先对各个设计模式的功能进行简要介绍,以便有个大概了解.后面的章节再进行详细介绍. 创建型模式 关注于怎么创建对象的 ...

  6. Java设计模式(一):设计模式概述、UML图、设计原则

    1 设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中. 1977年美国著名建筑大师.加利福尼亚大学伯克利分校环境结构 ...

  7. 设计模式(一)----设计模式概述及UML图解析

    1.设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中,而是被用于建筑领域的设计中. 1977年美国著名建筑大师.加利福尼亚大学伯克利分校环境结构 ...

  8. java 28 - 1 设计模式 之 面向对象思想设计原则和模版设计模式概述

    在之前的java 23 中,了解过设计模式的单例模式和工厂模式.在这里,介绍下设计模式 面向对象思想设计原则 在实际的开发中,我们要想更深入的了解面向对象思想,就必须熟悉前人总结过的面向对象的思想的设 ...

  9. 重学 Java 设计模式:实战访问者模式「模拟家长与校长,对学生和老师的不同视角信息的访问场景」

    作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 能力,是你前行的最大保障 年龄会不断的增长,但是什么才能让你不 ...

随机推荐

  1. C语言计算fastq文件GC含量2

    改进了一下,利用zlib可以读取gz格式的压缩文件,也可以直接计算非压缩格式 #include <stdio.h> #include <stdlib.h> #include & ...

  2. ubuntu20.04安装EasyConnect兼容性问题解决

    目录 1. 命令行启动EasyConnect 2. 降级pango 3. 重新启动EasyConnect,即可成功启动 Ubuntu20.04安装EasyConnect后无法启动的解决方案 工作使用操 ...

  3. 小程序https启用tls1.2

    公司的web服务器是iis7,在开发微信小程序的时候,需要启用TLS1.2. 将下面的代码复制到文本,存为reg文档,双击搞定. Windows Registry Editor Version 5.0 ...

  4. javaSE高级篇3 — 网络编程 — 更新完毕

    网络编程基础知识 先来思考两个问题( 在这里先不解决 ) 如何准确的找到一台 或 多台主机? 找到之后如何进行通讯? 网络编程中的几个要素 IP 和 端口号 网络通讯协议:TCP / UDP 最后一句 ...

  5. 商业爬虫学习笔记day3

    一. 付费代理发送请求的两种方式 第一种方式: (1)代理ip,形式如下: money_proxy = {"http":"username:pwd@192.168.12. ...

  6. 转Android service 启动篇之 startForegroundService

    本文转自:https://blog.csdn.net/shift_wwx/article/details/82496447 前言: 在官方文档 Android 8.0 行为变更 中有这样一段话: An ...

  7. Output of C++ Program | Set 13

    Predict the output of following C++ program. 1 #include<iostream> 2 using namespace std; 3 4 c ...

  8. zabbix之二进制安装

    #:参考官方网站 https://www.zabbix.com/documentation/4.0/manual/installation/install_from_packages/debian_u ...

  9. Oracle学习笔记(1)

    折腾了好久 终于把oracle安装成功了.小兴奋下. 创建了一个数据库 dabook. run--> Services.msc查看服务: 可以看到DABOOK的服务已启动. 1,sys用户 在c ...

  10. Java Log4j 配置文件

    ### 设置### log4j.rootLogger = debug,stdout,D,E ### 输出信息到控制抬 ### log4j.appender.stdout = org.apache.lo ...