1、桥接模式:它与建造者模式有相似之处,但区别也很明显。比如定套餐,加入套餐的搭配方式有限,比如啤酒只能配鸭,白酒只能配鸡,这时候使用建造者模式就有优势。但若是搭配方式完全灵活,那么套餐的种类就非常多了,这时候为每种组合定义一个套餐,就不划算了,这种情况就应该使用桥接模式了。
2、适配器模式:
(1)首先要说的是,在设计阶段不会用到这种设计模式。它的存在是为了应付紧急情况,快速修补服役中的程序。修补好之后,一般还是会整理代码。
(2)应用上讲,就是为了让旧的接口适应新的应用环境,而添加一个适配器,将旧接口与新环境适配。
(3)实现上讲,是要在实现类中增加适应新环境的代码。
3、过滤器模式:意义和实现都比较简单。有一堆对象,你需要按各种要求筛选一些组合时,就要用过滤器模式。实现过程主要就是编辑过滤器、组合过滤器,然后就拿到场景中应用就是。
4、组合模式:意义和实现都比较简单。有一堆相似的对象,他们之间的关系是典型的属性结构,其中的某些对象可以包含其它对象。最典型的例子就是界面中的View,所有控件其实都是View,但他们的结构就是树形关系,层层包含而成。显然View的设计,就是采用的组合模式。
5、装饰器模式:要扩展一个类的功能而不改变其结构,有两个方案供选择。一个是继承,一个是装饰器。继承不用说,这里说装饰器。一般来说,对象有一些基础功能,一开始设计就会有。然后会有一些可有可无的附加功能,后面一般会不断出现。如果继承用得太多,一旦涉及修改,那就是一大批子类跟着改。装饰器模式实际上就是用组合的方式替代了继承,将原类的功能集成到装饰器中,直接用装饰器替代原类。设计上一般是把基础功能设计到基础类中,然后针对附加功能设计装饰器。在使用中就直接使用装饰器,而不是哟就基础类。至于使用继承还是装饰器,一般在‘结构不稳定,不想增加很多子类’的情况下,就使用装饰器。但对于结构稳定且层次复杂的设计,使用继承也有其自身的优势。
6、外观模式:要去一个地方,我可以说打开车门、开车、各种转弯、找停车位、停车、锁车、到达等这样一个流程,也可以说开车去。当我只需要知道‘开车去’这样一个信息,不需要知道中间转了多少弯子,有过几个飘逸这些信息时,我就可以为一大顿流程提供一个简单的描述,这就是外观模式。外观模式的优点不用说,就是简化访问方式。这里重点说缺点:
(1)外观类是为多个子接口提供统一接口,以达到简化外部调用的目的。当需要暴露流程中的某些部分时,就需要外观类分开提供多个接口来实现这样的需求。但若需要定制的流程越来越多时,外观类就可能变得异常庞大。从这个角度讲,其使用情景有点类似建造模式:当流程只需要少数集中固定模式时,使用外观模式提供统一接口就有优势。若子接口的组合灵活多变时,就应该使用类似桥接模式的结构。需要讲的是,就算有外观类,我们也可以使用子接口,所以这种情况,子接口基本全部暴露了,就算写了外观类估计也用不上。
(2)由于客户与外观类耦合了,一旦子系统发生增删,外观类也要进行修改,直接违背了OCP(开闭原则);(缓解方法是对外观类进行抽象,但这又容易加大了代码量和冗余)
(3)在实战场景中,我很容易把外观模式与建造者模式等同,拿来与桥接模式进行比较取舍。
7、享元模式:用得太多了,最典型的是列表中的cell,不多说。
8、代理模式:先举个例子,就是iOS中的委托代理模式。委托者有一个代理者,某些功能需要代理者来实现。代理者可能是不同类型的对象,但它们都遵循代理协议(在java中的地位其实就是一个接口)。委托者只需在需要的时候向代理者发送命令去干事,不需要管代理者是什么类型。代理者也不需要管是谁在向他发命令,他只需要遵循代理协议,收到命令就干事。所以委托者和代理者不直接沟通,而是通过代理协议沟通,则就是代理模式。这样做的好处不言而喻,委托者依赖抽象接口而非具体对象,扩展性强。缺点自然就是多写了一层抽象,多了点工作量。代理模式说到底就是一种间接调用,类似适配器和装饰器,不过也有其特殊性:
(1)和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
(2)和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。
总结:桥接模式、过滤器模式、组合模式、外观模式、享元模式这几种结构型模式,都有鲜明的特点,比较容易理解和区分。但代理模式、适配器、装饰器三种,其实都是在原接口与接口调用者之间,增加一层抽象接口。区别在于:
(1)代理模式不会改变或增加功能,只是单纯的为了方便调用接口,对应到创建型模式中,有点类似工厂模式。只是工厂模式统一了所有接口,而代理模式只统一了某一项功能接口。在使用场景中,使用了代理接口,隐藏了原类。
(2)适配器:它会改变类本身的实现,在类的实现中引入适配器,并利用其适应新的需求。而新环境依然调用原类。说起来,这一点上也是特点鲜明,很好区分。
(3)装饰器模式:定义了装饰器类,在其中引入原类,拥有原类的所有功能,并添加了一些其它功能,相当于对原类的功能做了扩展,效用上类似于继承。在使用场景中,只使用装饰器,而隐藏了原类。装饰器是为了扩展原类,而代理模式则是单纯的为了与原类解藕,使用目的上也是很容易区分的。