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

参看: 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. Spring 注解开发

    目录 注解开发简介 常用注解 启用注解功能 bean 定义:@Component.@Controller.@Service.@Repository bean 的引用类型属性注入:@Autowired. ...

  2. MybatisPlus的CRUD及拓展

    创建一个简单的MybatisPlus项目在上一篇博客:MybatisPlus入门程序 一.CRUD 1. select 1.1 查找全部用户 //查 @Test public void select( ...

  3. Jumpserver堡垒机容器化部署

    JumpServer 是符合 4A 的专业运维安全审计系统. 前提条件 已部署docker Jumpserver 对外需要开放 80 443 和 2222 端口 服务器.数据库.redis 等依赖组件 ...

  4. 从零构建Java项目(Maven+SpringBoot+Git) #02 奥斯丁项目

    前两天我说要写个项目来持续迭代,有好多小伙伴都表示支持和鼓励,项目的第一篇这不就来了么~我给项目取了个名字,英文名叫做:austin,中文名叫做:奥斯丁 名字倒没有什么特别的含义,我单纯觉得这个名字好 ...

  5. 『学了就忘』Linux启动引导与修复 — 69、启动引导程序(grub)

    目录 1.启动引导程序(Boot Loader)简介 2.启动引导程序grub的作用 3.启动引导程序grub的位置 4./grub目录中其他的文件简单介绍 提示: 简单地说,Boot Loader就 ...

  6. 前端必须知道的 Nginx 知识

    Nginx一直跟我们息息相关,它既可以作为Web 服务器,也可以作为负载均衡服务器,具备高性能.高并发连接等. 1.负载均衡 当一个应用单位时间内访问量激增,服务器的带宽及性能受到影响, 影响大到自身 ...

  7. Linux基础命令---echo打印内容到标准输出

    echo echo指令可以输出内容到标准输出,以空白分割字符串,并且后面增加换行. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora.   1.语法       ec ...

  8. 使用NSURLSessionDownloadTask实现大文件下载-监听下载进度

    - 5.1 涉及知识点(1)创建NSURLSession并设置代理,通过NSURLSessionDownloadTask并以代理的方式来完成大文件的下载 //1.创建NSURLSession,设置代理 ...

  9. 理解JMX之介绍和简单使用

    JMX最常见的场景是监控Java程序的基本信息和运行情况,任何Java程序都可以开启JMX,然后使用JConsole或Visual VM进行预览.下图是使用Jconsle通过JMX查看Java程序的运 ...

  10. 【Linux】【Services】【Disks】zfs

    1. 简介: 据说zfs有去除重复数据的功能,无良人士继续要求吧samba共享盘使用的centos7上自带的xfs改成zfs,并且开启去重功能.samba配置见 http://www.cnblogs. ...