设计模式思考II
cfanr Lv4

*续 设计模式思考 I *

思考方式:
1.这种模式怎么理解?(尽量简单易懂)
2.类图怎样画?(代码怎样写)
3.举个栗子?(使用场景)
4.使用这种模式有什么优缺点?(遵循什么原则)

##结构型模式
###7.代理模式(Proxy) 
(1)理解
多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介。
(2)类图

UML-Proxy.png

(3)栗子
JDK动态代理,RMI(远程方法调用)
使用场景:
如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:
a.修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。
b.就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。

(4)优缺点
优:将功能划分的更加清晰,有助于后期维护
另外,代理模式,可以分为两种,一种是静态代理,一种是动态代理。
两种代理从虚拟机加载类的角度来讲,本质上都是一样的,都是在原有类的行为基础上,加入一些多出的行为,甚至完全替换原有的行为。
静态代理采用的方式就是我们手动的将这些行为换进去,然后让编译器帮我们编译,同时也就将字节码在原有类的基础上加入一些其他的东西或者替换原有的东西,产生一个新的与原有类接口相同却行为不同的类型。
动态代理是JDK自带的功能,它需要你去实现一个InvocationHandler接口,并且调用Proxy的静态方法去产生代理类。
详细: 代理模式详解(包含原理详解)

###8.适配器模式(Adapter)  
(1)理解
把一个类的接口变换成客户端所期待的另一种接口,从而使原本不匹配而无法在一起工作的两个,类能够在一起工作。分类:
a.组合(compositon, has-a关系):采用组合方式的适配器成为对象适配器
特点:把“被适配者”作为一个对象组合到适配器类中,以修改目标接口包装被适配者
b.继承(inheritance,is-a关系):采用继承方式的称为类适配器
特点:通过多重继承不兼容接口,实现对目标接口的匹配,单一的为某个类而实现适配(java是单继承)
(2)类图
插座适配器

UML-Adapter.png

(3)栗子
Android的ListView

ListAdapter.jpg

JDK里面的适配器模式应用:
•java.util.Arrays#asList()
•java.io.InputStreamReader(InputStream)
•java.io.OutputStreamWriter(OutputStream)

(4)优缺点
优:
a.透明
通过适配器,客户端可以调用同一个接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。
b.重用
复用了现存的类,解决了现存类和复用环境要求不一致的问题。
c.低耦合
将目标类和适配者类解耦,通过引入一个适配器重用现有的适配者类,而无需修改原有代码(遵循开闭原则)

###9.装饰器模式(Decorator)
(1)理解
装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

(2)类图

UML-Decorator.png

(3)栗子
JDK中装饰者模式的应用:java.io;java.util.Collections#synchronizedList(List);AWT和Swing图形组件
应用场景:
a.需要扩展一个类的功能。
b.动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删。)

(4)优缺点
优:可以根据功能需要有用户动态决定加入的方式和时机,实现“即插即用”的功能,在运行时动态决定增加何种功能。
缺:产生过多相似的对象,不易排错!

注:Decorator装饰设计模式和Proxy代理模式的区别(两者比较相似,都可以对目标对象做一些动态改变):
a.Proxy代理模式中,客户端不直接调用服务端程序,而是通过一个代理对象来调用服务端程序,类似一个请求转发的作用。
b. Decorator装饰设计模式中,被装饰对象可以不用添加任何装饰而直接使用,也可以通过装饰器的包装动态增强功能。

###10.桥接模式(Bridge)
(1)理解
桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化。将抽象化与实现化解耦,使得二者可以独立变化。

(2)类图

UML-Bridge.png

(3)栗子
JDBC桥DriverManager:JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,因为JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。

JDBC连接.PNG

(4)优缺点
优:遵循单一职责、迪米特、开闭原则,体现功能复用

注:Bridge桥接设计模式和Strategy策略设计模式区别:
a.Bridge桥接设计模式中不但实现可以变化,问题行为也是可以变化的,且两者的变化是相互独立的,在两个维度都存在变化情况下优先考虑使用桥接模式。
b.Strategy策略设计模式中,仅仅存在算法实现策略的变化,问题行为是不变的,即仅有一个维度的变化。另外策略模式中考虑的算法层次的变化,是无状态,无数据的。

###11.组合模式(Composite)
(1)理解
将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

(2)类图

组合模式.jpg

(3)栗子
适用于将多个对象组合在一起进行操作,常用于表示树形结构中,例如二叉树,数等。还有Android经常使用到,如View与ViewGroup

View与ViewGroup.jpg

(4)优缺点
优:简化代码,使得更容易添加新类型的组件,能够灵活控制基本对象与组合对象的使用。

注:详细还可分为两种形式,见 Composite设计模式

###12.享元模式(Flyweight)
(1)理解
享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。运用共享技术有效地支持大量细粒度的对象。
特点:享元模式基本是单例模式+简单工厂模式;减少运行时对象实例的个数,节省内存。

(2)类图

享元模式.jpg

(3)栗子
Android中SqliteDatabase中的mCompiledQuerie就是存放享元对象的容器;String常量池,JDBC连接池

(4)优缺点
优:减少内存的开销;有效地支持大量细粒度的对象

###13.外观模式(Facade)
(1)理解
外观设计模式为子系统中的一组接口提供一个一致的界面,应用程序本身将不再直接依赖于子系统原件,而是依赖一个门面,当想要修改某个原件的行为时,只需要修改实现类即可,应用程序本身不需要做任何修改。该模式没涉及到接口,降低了类类之间的耦合度。

(2)类图
以一个计算机的启动过程为例

UML-Facade.png

(3)栗子
JDK中java.util.logging和java.lang.Class
(4)优缺点
优:简化程序库的使用,隐藏所依赖​​的程序库,降低对程序库的耦合,有利于分工合作。
缺:隐藏了各个元件之间的合作行为,以及元件本身的操作与设定细节,失去了一些直接操作元件的方便性。

参考:
1.Java之美[从菜鸟到高手演变]之设计模式-终点
2.Android设计模式系列-谦虚天下
3.设计模式系列-Tony Chen
4.设计模式详解-左潇龙
5.设计模式UML类图