设计模式,现在在网上随便搜都一大堆,为什么我还要写“设计模式”的章节呢?

两个原因:

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模式,人人能懂的有趣实例的更多相关文章

  1. 设计模式之——visitor模式

    visitor模式,又叫访问者模式,把结构和数据分开,编写一个访问者,去访问数据结构中的元素,然后把对各元素的处理全部交给访问者类.这样,当需要增加新的处理时候,只需要编写新的 访问者类,让数据结构可 ...

  2. 设计模式之Visitor模式(笔记)

    訪问者模式:表示一个作用于某个对象结构中的各元素操作.它使你能够不改变各元素的类的前提下定义作用于这些元素的新操作. 首先定义一个visitor抽象类,为每一个详细类声明一个visit操作 publi ...

  3. 设计模式:visitor模式

    核心:将数据结构和数据的处理分开 注意:注意函数的参数传递和调用关系 例子: class Element; class Visitor { public: virtual void Visit(Ele ...

  4. 大话设计模式--职责连模式 Chain of Resposibility -- C++实现实例

    1. 职责链模式: 使多个对象都有机会处理请求,从而避免请求发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它. 当客户提交一个请求时,请求是沿着链传递直 ...

  5. [设计模式] 23 访问者模式 visitor Pattern

    在GOF的<设计模式:可复用面向对象软件的基础>一书中对访问者模式是这样说的:表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作.访问 ...

  6. 乐在其中设计模式(C#) - 访问者模式(Visitor Pattern)

    原文:乐在其中设计模式(C#) - 访问者模式(Visitor Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 访问者模式(Visitor Pattern) 作者:webabc ...

  7. 设计模式:基于线程池的并发Visitor模式

    1.前言 第二篇设计模式的文章我们谈谈Visitor模式. 当然,不是简单的列个的demo,我们以电商网站中的购物车功能为背景,使用线程池实现并发的Visitor模式,并聊聊其中的几个关键点. 一,基 ...

  8. 设计模式---行为变化模式之访问器模式(Visitor)

    一:概念 访问者模式,是行为模式之一,它分离对象的数据和行为,使用Visitor模式,可以不修改已有类的情况下,增加新的操作角色和职责. 二:动机 在软件构建的过程中,由于需求的改变,某些类层次结构中 ...

  9. Java设计模式(三) Visitor(訪问者)模式及多分派场景应用

    基本概念 Visitor 封装一些作用于数据结构中的各元素的操作,不同的操作能够借助新的visitor实现.减少了操作间的耦合性 訪问者能够将数据结构和对数据的操作解耦,使得添加对数据结构的操作不须要 ...

随机推荐

  1. 【1414软工助教】团队作业2——需求分析&原型设计 得分榜

    题目 团队作业2--需求分析&原型设计 作业提交情况情况 本次作业所有团队都按时提交作业. 往期成绩 个人作业1:四则运算控制台 结对项目1:GUI 个人作业2:案例分析 结对项目2:单元测试 ...

  2. 201521044091 《Java学习笔记》 第六周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结.注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖面 ...

  3. 201521123022 《Java程序设计》 第二周学习总结

    1. 本章学习收获 (1)在老师指导下学会如何使用码云管理代码,代码不仅是保存到本地,还需要Push到码云这个"仓库"里. (2)JDK源代码可以为我们的编程提供许多便利之处,应善 ...

  4. 201521145048 《Java程序设计》第7周学习总结

    1. 本周学习总结 2. 书面作业 Q1.ArrayList代码分析 1.1 解释ArrayList的contains源代码 1.2 解释E remove(int index)源代码 1.3 结合1. ...

  5. 201521123039《Java程序设计》第十三周学习总结

    1. 本周学习总结 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? 下面是IP地 ...

  6. Python学习笔记005_文件_OS_模块_pickle

    >>> >>> # 文件 open()方法是打开文件,它有很多参数,第一个文件名是必须的(带路径)>>> >>> f = ope ...

  7. Linux 虚拟机安装后的配置和一些命令符笔记

    一.安装后的配置 1.设在终端的字体为等宽字体 比如:DejaVu Sans Mono 2.将当前的普通用户加入到sudo用户组adduser en sudochmod +w /etc/sudoers ...

  8. MySQL线程池的引入可以提高我们的MySQL的性能

    支持线程池的版本:MySQL 企业版本,MySQL percona的分支 MariDB 的版本.我们知道我们的MySQL 语句是不支持硬解析的,没有无SQL 解析 cache.每个连接对应一个线程,我 ...

  9. Thinkphp3.2版本使用163邮箱发(验证码)邮件

    今天忽然想写一个用户修改密码的功能,又没有短信接口,只能选择用邮箱发送验证码啦,穷啊,没办法,哈哈,以下为正文. ------------------------------------------- ...

  10. 简单实用的CSS网页布局中文排版技巧

    由于汉字的特殊性,在css网页布局中,中文排版有别于英文排版.排版是一个麻烦的问题,小编认为,作为一个优秀的网页设计师和网页制作人员,掌握一些简单的中文排版技巧是不可或缺的,所以今天特意总结了几个简单 ...