设计模式,Let's “Go”! (下)

前言

接上篇 设计模式,Let's “Go”! (中), 继续更新设计模式,今天介绍的设计模式有责任链模式、蝇量模式、解释器模式、中介者模式、备忘录模式、原型模式和访问者模式;

文章对设计模式的特点和使用场景进行了总结,每个设计模式分配的篇幅较少,给了解过设计模式的作为速查,帮不了解设计模式的入门, 当然具体实现才是重点,使用现实生活中的事物例子来帮助理解设计模式。

搭配源码食用更佳,放上 Go 实现设计模式的源码地址:DesignPattern-枕边书-Github ,偶有更新,欢迎 star

文章经常被人爬,而且还不注明原地址,我在这里的更新和纠错没法同步,这里注明一下原文地址:http://www.cnblogs.com/zhenbianshu/p/7506537.html 以防误人子弟。

正文开始:

责任链模式(Chain of Responsibility)

介绍

责任链模式:将请求处理者串成“链”依次尝试处理请求,以此解耦请求和处理者;

  • 责任链模式将任务处理者划分先后次序,依次尝试,直到任务被处理;
  • 每个处理者存储自己的下一环;任务开始时选择最靠前的处理者试图处理任务;
  • 在遇到自己无法处理的情况,传递给自己的下一环来处理;

场景

  • 适用于单个任务,多个处理者;
  • 需要依次尝试处理者;

实现

  1. 公司里 leader、经理和CEO有不同额度的报销限额;
  2. leader报销不了的金额交给经理,而经理将自己处理不了的给CEO处理;
  3. 张三要报销200元,leader就能批准;
  4. 李四要报销8000元,leader报销不了,就交给经理,经理也处理不了,最后交给CEO报销;

蝇量模式(Flyweight)

介绍

蝇量模式:使用一个对象存储和模拟多个虚拟对象,大大减少多个对象的内存占用。

  • 实例化多个相似实例会占用较多内存空间,蝇量模式使用一个对象类变量保存多个对象的属性,以一个对象控制多个对象;
  • 蝇量模式可以极大地减少内存占用,也可以方便对多个对象进行统一管理
  • 实例一旦实现了蝇量模式,那么单个实例就无法再独立拥有不同的行为;

场景

  • 有很多相似对象,拥有相同的属性项和方法;
  • 多个对象只会被统一调用;

实现

  • 在一片森林中,有很多大树,他们都只有高度一个属性;
  • 将多个大树的属性保存一个森林对象的 map 中;
  • 调用森林的砍伐方法,砍伐森林中所有的树;

解释器模式(Intepreter)

介绍

解释器模式:定义一种方法和对应的解释器,使用解释器解释此方法的语句来执行;

  • 解释器模式需要上下文类来定义和存储上下文,解释器类用来将语句来翻译成可执行程序;
  • 解释器扩展和改变文化非常简单,构建完成后可以很方便地数据格式;
  • 解释器模式会将非终结表达式递归解释,直到解释为终结符表达式;

场景

  • 解释器模式适用于数据结构不规则,但数据要素相同的情况;
  • 语法不能太复杂,复杂的最好使用解释形语言来实现以降低复杂性;

实现

  1. 在php中,php环境是上下文;
  2. 字符串值不能再向下解释了,如 "hello" "greeting" 都是终结符;
  3. 在上下文中定义了两个变量 $greeting = "hello"; $test = "greeting";
  4. 现在来解释变量 $$test = "hello";

中介者模式(Mediator)

介绍

中介者模式:通过一个中介对象封装多个对象之间的交互,解耦各个对象之前的相互依赖;

  • 对象之间通过中介者进行交互,不必再显示调用目标对象;
  • 中介者对对象之间的关系进行了封装,减少了对象之间的耦合,使得对象可以独立改变和复用;
  • 中介者模式与适配器模式和代理模式的不同之处:三者都通过中间对象解决对象之间的沟通问题,但他们要解决的问题和解决问题的对象都不同;

场景

  • 中介者模式适合多对多的对象交互情况;
  • 中介者适合对象之间交互较多,依赖复杂的情况;

实现

  1. 联合国作为多个国家之间的中间人存在,各国家之间通过联合国沟通;
  2. 法国和韩国尝试通过联合国隔空对话;
  3. 他们双方只向联合国喊话,并从联合国处获取对方国家的回应;

备忘录模式(Memento)

介绍

备忘录模式:使用一个备忘录对象记录并保存对象内部状态,并能随时恢复到保存的状态;

  • 备忘录对象是一个类似于目标对象的轻量级对象,它保存着目标对象的可变属性;
  • 备忘录保管者可以保存多个备忘录,并将对象恢复到任一时刻; ###场景
  • 备忘录模式适用于需要保存对象历史状态用以支持撤销的场景;

实现

  1. 时光掌控者保存着许多人类世界的“时间快照”;
  2. 小明18岁时身高175,体重70,时光掌控者此时获取小明的信息产生了一个快照;
  3. 小明在不停地长大,80岁时身高170,体重65;
  4. 时光掌控者选择小明18岁的快照对小时进行了恢复,小明又回到了18岁;

原型模式(Prototype)

介绍

原型模式:通过复制原型对象修改属性的方式来快速创建新对象;

  • 原型模式通过抽象多个对象的相同属性和方法来设置一个原型;
  • 原型模式可以通过原型对象设置对象的基本属性,减少创建出的对象的开放;
  • 原型模式使得调用者只知道对象的原型而不必了解创建过程即可创建一个新对象;

场景

  • 原型模式适用于对象较大或创建过程较复杂的情况;
  • 适用于需要创建多个有共同“原型”的对象,也即它们拥有大部分共同属性;

实现

  1. 据说国家仪仗队的队员都是 年龄20岁、身高180、体重72kg的男性士兵;
  2. 抽象一个“年龄20岁、身高180、体重72kg”的人作为仪仗队员的“原型”;
  3. 创建一个仪仗队员原型,并设置姓名来产生一个真实的仪仗队员对象;

访问者模式(Visitor)

介绍

访问者模式:将对一些对象的访问过程抽象出类,以实现在不改变对象的前提下对这些对象添加操作;

  • 访问者模式分离对象的数据结构和数据操作
  • 访问者模式将数据的访问方法集中到一个类中作为访问者,便于对数据访问的统一管理;
  • 如果数据有添加或删除,需要修改多个访问者;

场景

  • 访问者模式适用于数据结构稳定的类;
  • 对对象的同一种数据有多种不同的操作方式;

实现

  1. 超市里的商品都有 名称和价格 两种属性,顾客使用购物车保存了要买的商品;
  2. 设置一个打印机访问者,访问并打印顾客购物车内的商品名称;
  3. 如果要添加一个商品价格计算器,只需要实现与打印机相同的访问者接口,访问并计算购物车中商品的价格;

小结

最后说一下设计模式的分类,根据设计模式所针对的问题,将设计模式分为三类:

  • 创建型,创建型模式针对对象的创建。包括:工厂模式、单例模式、生成器模式、原型模式;
  • 行为型,行为型模式针对对象的行为,如对象之间的通信、职责分配。包括:策略模式、观察者模式、状态模式、模板模式、命令模式、迭代器模式、责任链模式、中介者模式、解释器模式、备忘录模式、访问者模式。
  • 结构型,结构型模式针对如何实现对象的结构。包括:装饰者模式、适配器模式、外观模式、桥接模式、组合模式、代理者模式、蝇量模式。

设计模式的目标,是用来解决通用问题的。一个项目也不可能只有一种问题,所以在真正的使用中,还是要将不同的设计模式组合使用,总而言之:多想、多写

关于本文有什么问题可以在下面留言交流,如果您觉得本文对您有帮助,可以点击下面的 推荐 支持一下我。一直在更新,欢迎 关注

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏铭毅天下

干货 | Elasticsearch Nested类型深入详解

本文通过一个例子将Nested类型适合解决的问题、应用场景、使用方法串起来, 文中所有的DSL都在Elasticsearch6.X+验证通过。

1613
来自专栏大内老A

ASP.NET MVC下的四种验证编程方式

ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效性...

2227
来自专栏资深Tester

测试流程之如何设计测试用例

1803
来自专栏Java编程

Java 异常处理的误区和经验总结

本文着重介绍了 Java 异常选择和使用中的一些误区,希望各位读者能够熟练掌握异常处理的一些注意点和原则,注意总结和归纳。只有处理好了异常,才能提升开发人员的基...

5771
来自专栏乐百川的学习频道

设计模式(二十四) 访问者模式

访问者模式提供了一种方法,将算法和数据结构分离。假设我们需要对一个数据结构进行不同的操作,就可以考虑使用访问者模式。访问者模式的要点在于,需要一个访问者接口,提...

2116
来自专栏编程

改进异常处理的 6 条建议

来源:ImportNew - 唐尤华 , 合理地使用异常处理可以帮你节省数小时(甚至数天)调试时间。一个乘法异常会毁掉你的晚餐乃至周末计划。如果处置不及时,甚至...

2229
来自专栏海纳周报

用Atomic实现锁

一直想写ReentrantLock,就得先介绍AbstractQueueSynchronizer,可是我觉得这样写,不过瘾,我把代码贴一遍,懂的人自己就能找到这...

3536
来自专栏有趣的django

PYTHON面试

大部分的面试问题,有最近要找事的老铁吗?  python语法以及其他基础部分 可变与不可变类型;  浅拷贝与深拷贝的实现方式、区别;deepcopy如果你来...

5567
来自专栏Java架构

2018年Java程序员最新BAT面试题

3336
来自专栏精讲JAVA

用 Maven 实现一个 protobuf 的 Java 例子

Protocal Buffers(简称protobuf)是谷歌的一项技术,用于结构化的数据序列化、反序列化,常用于RPC 系统(Remote Procedure...

1142

扫码关注云+社区