《Head First 设计模式》后传(A)—— 剩下的模式

相关模式代码

桥接模式 bridge--遥控器的设计

使用桥接模式不只改变你的实现,也改变你的抽象。
桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。
遥控器很多电视,遥控器要按照一定规则对电视进行控制。遥控器要改变,电视也会改变。

有了桥接的存在,你可以独立的修改遥控器和电视机的实现。

优点:

  将实现予以解耦,让它和界面之间不再永久绑定。
  抽象和实现可以独立扩展,不会影响到对方。
  对于“具体的抽象类”所做的改变,不会影响到客户。

用途:

  适合使用在需要跨越多个平台的图形和窗口系统上。
  当需要用不同的方法改变接口和实现时,你会发现桥接模式很好用。

缺点:

  桥接模式的缺点是增加了复杂度。

我想到的

还想到的有JDBC的连接,mysql和oracle的就像是不同的电视,而自己控制这些数据库具体要用哪些Statement也是要具体决定的,于是就是虚拟的Statement具体操纵虚拟的数据库接口。用的时候你既要实现具体某个数据库用哪个,还要决定你的Statement语句怎么写,中间互不影响。

生成器模式 builder--指定度假计划

使用生成器模式(Builder Pattern)封装一个产品的构造过程,并允许按步骤构造。
现在制定度假计划,每个客人的度假计划可能都不太一样。我们将旅游规划的创建过程,封装到一个对象中(称此对象为生成器),然后让客户调用生成器为它创建旅游规划。

Builder(抽象建造者):它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两类方法,一类方法是buildPartX(),它们用于创建复杂对象的各个部件;另一类方法是getResult(),它们用于返回复杂对象。Builder既可以是抽象类,也可以是接口。
ConcreteBuilder(具体建造者):它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象,也可以提供一个方法返回创建好的复杂产品对象。
Product(产品角色):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。在本类图中,产品类是一个具体的类,而非抽象类。实际编程中,产品类可以是由一个抽象类与它的不同实现组成,也可以是由多个抽象类与他们的实现组成。
Director(指挥者):指挥者又称为导演类,负责调用适当的建造者来组建产品,导演类一般不与产品类发生依赖关系,与导演类直接交互的是建造者类。一般来说,导演类被用来封装程序中易变的部分。

优点:

  将一个复杂对象的创建过程封装起来。
  允许对象通过多个步骤来创建,并且可以改变过程(这和只有一个步骤的工厂模式不同)。
  向客户隐藏产品内部的表现。
  产品的实现可以被替换,因为客户只看到一个抽象的接口。

用途:

  经常被用来创建组合结构。

缺点:

  与工厂模式相比,采用生成器模式创建对象的客户,需要具备更多的领域知识。

我想到的

我见到的builder比较多的一个是jsonbuilder、querybuilder、http请求的builder,但是本质上都是jsonbuilder。

责任链 Chain of Responsibility--邮件过滤

对于一个公司邮件有粉丝的邮件--投诉--合作--垃圾邮件,如果每个请求要经过这样的流程然后分别处理,就很适合责任链模式

优点:

将请求的发送者和接收者解耦。
可以简化你的对象,因为它不需要知道链的结构。
通过改变链内的成员或调动它们的次序,允许你动态地新增或者删除责任。 

用途:

经常被使用在窗口系统中,处理鼠标和键盘之类的事件

缺点:

并不保证请求一定会被执行;如果没有任何对象处理它的话,它可能会落到链尾端之外(这可以是优点也可以是缺点)。
可能不容易观察运行时的特征,有碍于除错。

我想到的

很多事就是这样的,比如java web里component的扫描bean,index.html等相关顺序。

蝇量模式 flyweight--景观设计中的树

如想让某个类的一个实例能用来提供许多“虚拟实例”,就使用蝇量模式(Flyweight Pattern) 。

优点:

减少运行时对象实例的个数,节省内存。
将许多“虚拟”对象的状态集中管理。

用途:

当一个类有许多的实例,而这些实例能被同一方法控制的时候,我们就可以使用蝇量模式。

缺点:

蝇量模式的缺点在于,一旦你实现了它,那么单个的逻辑实例将无法拥有独立的而不同的行为。

我想到的

蝇量模式的实例没有什么太多个性化的东西,基本都可以和构造方法的相关属性是相关的。

解释器模式 interpreter--教孩子编程

如想让某个类的一个实例能用来提供许多“虚拟实例”,就使用蝇量模式(Flyweight Pattern) 。

优点:

将每一个语法规则表示成一个类,方便于实现语言。
因为语法由许多类表示,所以你可以轻易地改变或扩展此语言。
通过在类结构中加入新的方法,可以在解释的同时增加新的行为,例如打印格式的美化或者进行复杂的程序验证。

用途:

当你需要实现一个简单的语言时,使用解释器。
当你有一个简单的语法,而且简单比效率更重要时,使用解释器。
可以处理脚本语言和编程语言。

缺点:

当语法规则的数目太大时,这个模式可能会变得非常繁杂。在这种情况下,使用解释器/编译器的产生器可能更合适

我想到的

解释器还不如写成面向切面的log

中介者 mediator -- 什么时间做什么事情

一个自动屋,但是其中有着复杂的规则。想要持续地追踪每个对象的每个规则,以及众多对象之间彼此错综复杂的关系,实在不容易。
在这个系统中加入一个中介者,一切都变得简单了,没有中介者,所有人都要认识其他人,规则在各个对象之间很繁琐:

每个对象都会在自己的状态改变时,告诉中介者。
每个对象都会对中介者所发出的请求作出回应。
中介者负责所有逻辑,对象之间彻底解耦

优点:

通过将对象彼此解耦,可以增加对象的复用性。
通过将控制逻辑集中,可以简化系统维护。
可以让对象之间所传递的消息变得简单而且大幅减少。

用途:

中介者常常被用来协调相关的GUI组件。

缺点:

中介者模式的缺点是,如果设计不当,中介者对象本身会变得过于复杂。

我想到的

前面说了,MVC都有人说是中介者,其实有的MVC确实是。
很多通信也是中介者,比如socket通信。

备忘录 memento--游戏存档

使用备忘录模式有两个目标:
1.储存系统关键对象的重要状态。
2.维护关键对象的封装。
请不要忘记单一责任原则,不要把保持状态的工作和关键对象混在一起,这样比较好。这个专门掌握状态的对象,就称为备忘录。

优点:

将被储存的状态放在外面,不要和关键对象混在一起,这可以帮助维护内聚。
保持关键对象的数据封装。
提供了容易实现的恢复能力。

用途:

备忘录用于储存状态。

缺点:

储存和恢复状态的过程可能相当耗时。
Java系统中,其实可以考虑使用序列化(serialization)机制储存系统的状态。

我想到的

为了节约内存,可使用原型模式+备忘录模式。

原型 prototype--创建怪兽,先有个原型

交互式角色扮演游戏中的各种怪兽生成,并希望高级用户能够创建自己的怪兽。
原型模式允许你通过复制现有的实例来创建新的实例(在Java中,这意味着使用clone()方法,或者反序列化)。
这个模式的重点在于,客户的代码在不知道要实例化何种特定类的情况下,可以制造出新的实例。

优点:

向客户隐藏制造新实例的复杂性。
提供让客户能够产生未知类型对象的选项。
在某些环境下,复制对象比创建新对象更有效。

用途:

在一个复杂的类层次中,当系统必须从其中的许多类型创建新对象时,可以考虑原型。

缺点:

使用原型模式的缺点:对象的复制有时相当复杂。

我想到的

浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。

访问者 visitor--餐厅顾客询问食物相关的营养信息

当你想要为一个对象的组合增加新的能力,且封装并不重要时,就使用访问者模式(Visitor Pattern) 。
餐厅顾客询问食物相关的营养信息。
访问者必须参观组合内的每个元素;这样的功能是在导游(Traverser)对象中,访问者通过导游的引导,收集组合中所有对象的状态。
一旦状态被收集了,客户就可以让访问者对状态进行各种操作。
当需要新的功能时,只要加强访问者即可。

优点

允许你对组合结构加入新的操作,而无需改变结构本身。
想要加入新的操作,相对容易。
访问者所进行的操作,其代码是集中在一起的。

缺点

当采用访问者模式的时候,就会打破组合类的封装。
因为游走的功能牵涉其中,所以对组合结构的改变就更加困难。

我想到的

这个我不找你,你来找我,不过不是看到真的我,给你关于我的导游,你来选怎么看我

发表评论

电子邮件地址不会被公开。