设计模式之visitor模式,人人能懂的有趣实例
设计模式,现在在网上随便搜都一大堆,为什么我还要写“设计模式”的章节呢?
两个原因:
1.本人觉得这是一个有趣的设计模式使用实例,所以记下来;
2.看着设计模式很牛逼,却不知道怎么在实战中应用出来。希望这个实例能给学习者一个参考,一点启发。
注意:本文是个人对设计模式的见解,不会出现大家常见的设计模式的概念。此文只作为一个实例。建议初学者参杂着别人博文一起读。
在此,向《大话设计模式》作者吴强前辈致敬
一、 Visitor(访问者)模式
关键词:访问者, 被访问者(元素),元素群,双重注入,操作
访问者模式的作用:对【元素】、【访问者】和【对元素的操作】进行单独抽象和封装,一旦这些【访问者】的增加或者是【对元素的操作】发生变化,不需要修改【元素】。
二、故事背景
程序员小明到了新的软件园,呆了半个月之后,发现附近没有快餐店,人流特别多。于是决定投资开一家快餐店,参考"某乐园"的运营模式。快餐店很快就装修好了。小明参考各路快餐店,很快就设计出了几款菜式。经过深思熟虑,小明对点餐计费环节,用了Visitor模式。
三、设计分析
每道菜(为了直观,这里没用商品,而是把汤和饭也作为菜品之一)作为最小的单元(元素);
每个点餐的客户作为访问者;
每一份快餐的菜单,则归类为对菜的操作。
四、参考事例
1.菜的抽象父类
public abstract class Element {
protected String name; //菜名
protected float price; //价格
protected int weight; //份量
abstract public void 供给(Visitor visitor);
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
} }
2.食客接口
public interface Visitor {
abstract public void 选菜( Element element );
}
3.各种菜品继承菜的父类
/**
* 卷心菜
* @author 南城草
*
*/
public class Cabbage extends Element { public Cabbage(int weight) {
this();
this.weight = weight;
this.price = price*weight;
}
public Cabbage() {
this.name = "卷心菜";
this.price = 2;
this.weight = 1;
} @Override
public void 供给(Visitor visitor) {
visitor.选菜(this);
} }
/**
* 饭
* @author 南城草
*
*/
public class Meal extends Element { public Meal(int weight) {
this();
this.weight = weight;
this.price = price*weight;
}
public Meal() {
this.name = "饭";
this.price = 2;
this.weight = 1;
} @Override
public void 供给(Visitor visitor) {
visitor.选菜(this);
} }
/**
* 烧鸭
* @author 南城草
*
*/
public class RoastDuck extends Element { public RoastDuck(int weight) {
this();
this.weight = weight;
this.price = price*weight;
}
public RoastDuck() {
this.name = "烧鸭";
this.price = 8;
this.weight = 1;
} @Override
public void 供给(Visitor visitor) {
visitor.选菜(this);
} }
/**
* 叉烧
* @author 南城草
*
*/
public class RoastPork extends Element { public RoastPork(int weight) {
this();
this.weight = weight;
this.price = price*weight;
}
public RoastPork() {
this.name = "叉烧";
this.price = 8;
this.weight = 1;
} @Override
public void 供给(Visitor visitor) {
visitor.选菜(this);
} }
/**
* 汤
* @author 南城草
*
*/
public class Soup extends Element { public Soup(int weight) {
this();
this.weight = weight;
this.price = price*weight;
}
public Soup() {
this.name = "汤";
this.price = 3;
this.weight = 1;
} @Override
public void 供给(Visitor visitor) {
visitor.选菜(this);
} }
……后面省略了快餐店多种菜式
4.普通客户 实现访客者(Visitor)接口
/**
* 普通客户
* @author 南城草
*
*/
public class NormalVisitor implements Visitor { @Override
public void 选菜(Element element) {
Element food = ((Element) element);
System.out.println(food.getName() +food.getWeight()+ "份!");
} }
……后面省略多种不同客户的优惠实现(什么会员用户打折,会员积分都在这里拓展)
5.下单类
/**
* 普通菜单
* @author 南城草
*
*/
public class Lunchbox {
private HashMap<String, Element> elements;
private float allPrice = 0; public Lunchbox() {
elements = new HashMap();
} public void Attach(Element element) {
elements.put(element.getName(), element);
} public void Detach(Element element) {
elements.remove(element);
} public Element getElemente(String name) {
return elements.get(name);
} public void Accept(Visitor visitor) {
for (Element e : elements.values()) {
e.供给(visitor);
allPrice += e.getPrice() * e.getWeight();
}
System.out.print("总价:"+allPrice);
}
}
……这里省略了多种点餐单,什么节日满减,都可以在这里拓展
5.测试类——一个普通用户过来,要点菜啦
public class MainTest {
public static void main(String[] args) {
Lunchbox lunchbox = new Lunchbox(); lunchbox.Attach(new RoastDuck(1));
lunchbox.Attach(new Meal(2));
lunchbox.Attach(new Soup(1)); lunchbox.Accept(new NormalVisitor());
} }
6.测试结果
饭1份!
烧鸭1份!
汤1份!
总价:15.0
三、总结
访客模式的优缺点:这里不做总结,百度很多。
事例中的优缺点:
优点:菜品的新增,直接增加类就可以了;
访客的变化,直接增加类实现接口就可以了;
制定新的销售手段,直接增加下单类就可以了;
这符合“开闭原则”。
缺点:很明显,不能对菜品进行修改。
四、与本章节无关
本人技术有限,如果错误或者不合理的地方,欢迎联系我整改。
突然写此章节,是一个偶然的机会,想到了这个有趣的设计模式例子,就写了下来。后续如果生活中发现符合其它设计模式的有趣例子,会持续增加。
设计模式之visitor模式,人人能懂的有趣实例的更多相关文章
- 设计模式之——visitor模式
visitor模式,又叫访问者模式,把结构和数据分开,编写一个访问者,去访问数据结构中的元素,然后把对各元素的处理全部交给访问者类.这样,当需要增加新的处理时候,只需要编写新的 访问者类,让数据结构可 ...
- 设计模式之Visitor模式(笔记)
訪问者模式:表示一个作用于某个对象结构中的各元素操作.它使你能够不改变各元素的类的前提下定义作用于这些元素的新操作. 首先定义一个visitor抽象类,为每一个详细类声明一个visit操作 publi ...
- 设计模式:visitor模式
核心:将数据结构和数据的处理分开 注意:注意函数的参数传递和调用关系 例子: class Element; class Visitor { public: virtual void Visit(Ele ...
- 大话设计模式--职责连模式 Chain of Resposibility -- C++实现实例
1. 职责链模式: 使多个对象都有机会处理请求,从而避免请求发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它. 当客户提交一个请求时,请求是沿着链传递直 ...
- [设计模式] 23 访问者模式 visitor Pattern
在GOF的<设计模式:可复用面向对象软件的基础>一书中对访问者模式是这样说的:表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作.访问 ...
- 乐在其中设计模式(C#) - 访问者模式(Visitor Pattern)
原文:乐在其中设计模式(C#) - 访问者模式(Visitor Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 访问者模式(Visitor Pattern) 作者:webabc ...
- 设计模式:基于线程池的并发Visitor模式
1.前言 第二篇设计模式的文章我们谈谈Visitor模式. 当然,不是简单的列个的demo,我们以电商网站中的购物车功能为背景,使用线程池实现并发的Visitor模式,并聊聊其中的几个关键点. 一,基 ...
- 设计模式---行为变化模式之访问器模式(Visitor)
一:概念 访问者模式,是行为模式之一,它分离对象的数据和行为,使用Visitor模式,可以不修改已有类的情况下,增加新的操作角色和职责. 二:动机 在软件构建的过程中,由于需求的改变,某些类层次结构中 ...
- Java设计模式(三) Visitor(訪问者)模式及多分派场景应用
基本概念 Visitor 封装一些作用于数据结构中的各元素的操作,不同的操作能够借助新的visitor实现.减少了操作间的耦合性 訪问者能够将数据结构和对数据的操作解耦,使得添加对数据结构的操作不须要 ...
随机推荐
- 【Alpha】——First scrum Meeting
一.今日站立式会议照片 二.每个人的工作 成员 昨天已完成的工作 今天计划完成的工作 · 李永豪 编写测试计划 学习JAVA编程及UI设计 · 郑靖涛 Alpha任务分配计划 学习JAVA编程及UI设 ...
- 201521123022 《Java程序设计》 第六周学习总结
1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 2. 书面作业 Q1.clone方法 Q1.1 Objec ...
- 201521123006 《Java程序设计》第5周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 接口与抽象类拥有相同之处:(1)都代表系统的抽象层. (2)都不能被实例化(不能 ...
- 201521123019 《Java程序设计》第10周学习总结
1. 本周学习总结 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出现学号) 1.2 4-2中finally中捕获异常需要注意什么? 只有执 ...
- 201521123048 《Java程序设计》第14周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自 ...
- 从GO内存模型与调用协议理解defer closure的坑
资料参考: 官网defer介绍: https://blog.golang.org/defer-panic-and-recover 深入解析go: 多值返回: https://tiancaiamao.g ...
- geotrellis使用(三十三)关于Geotrellis读取Geotiff的两个细节
前言 在上两篇文章中我介绍了如何直接将Geotiff(一个或者多个)发布为TMS服务.这中间其实我遇到了一个问题,并且这个问题伴随Geotrellis的几乎所有使用案例,下面我进行详细讲述. 一.问题 ...
- jmeter 分布式实战
最近作者在公司部署公司的分布式压力测试情况的时候,遇到了问题,什么问题呢,各种错误,于是大晚上的为了不耽误压测,我们就两个同事两台电脑搞,可是还是不行的呢,我要研究研究这个是什么梗,于是乎,大晚上加班 ...
- 出现java.sql.SQLException: No suitable driver的几种解决办法
今天在用C3p0连接MySql数据库 这个时候出现了上面的错误, 一般来说这种错误有3个方向解决 一般都是db的配置的问题 ,一定要小心DB 的配置 八月 19, 2017 8:30:46 下午 co ...
- Linux Ubuntu从零开始部署web环境及项目 -----tomcat+jdk+mysql (二)
上一篇介绍如何在linux系统下搭建ssh环境 这篇开始将如何搭建web服务器 1,下载文件 在官网下载好 tomcat.jdk.mysql的linux压缩包 后缀名为.tar.gz 并通过xftp上 ...