结构型模式总结

  结构型模式,一共有 7 个,即 Adapter, Bridge, Composite, Decorator, Façade, Flyweight Proxy 。分别总结如下:

 

一、 Adapter模式

Adapter模式有两种形式:对象适配器和类适配器。

 

1.     对象适配器

结构型模式总结_第1张图片

上图为对象适配器UML类图。在对象适配器形式下,Adapter类中需要拥有一个Adaptee对象adaptee,然后通过该对象去调用Adaptee类中的specific_request函数。

 

2.     类适配器

上图为类适配器UML类图。在类适配器形式下,类Adapter通过继承类Adaptee的方式,从而可以获取specific_request函数的访问权。

 

“Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces." - GoF

 

二、 Bridge模式

结构型模式总结_第2张图片 

Bridge模式主要用于解决2个维度变化的问题。比如在游戏开发中,不同型号的坦克需要在不同的操作系统平台上实现,不同型号的坦克是一个变化的维度,不同操作系统平台上的实现是另外一个维度。

 

“Decouple an abstraction from its implementation so that the two can vary independently.” - GoF

 

使用Bridge模式可以大幅度降低子类的数量。

 

三、  Composite模式

在面向对象的系统中,我们经常会遇到一类具有容器特征的对象,即它们在充当对象的同时,又是其他对象的容器。比如,在操作系统中,文件的概念很广泛,其中文件可以是普通文件,也可以是目录(Unix中,设备也是文件),目录中可以存放文件。Composite设计模式就是将客户代码与复杂的对象容器结构解耦,让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象(文件)一样来处理复杂的对象容器(目录)

调用Directory类对象的process函数,和调用PhysicalFile类对象的process一样简单。

 

从上面的UML类图中,可以看出DirectoryFile这两个类之间的关系:

1.       Directory “is a”File

2.       Directory “has a(more)” File

这是典型的递归结构。因此在处理递归问题时,如果必要,可以考虑采用Composite模式。后面要讲到的Decorator模式也是如此。

 

“Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.” – GoF

 

四、 Decorator模式

结构型模式总结_第3张图片 

Decorator设计模式,就是使对象功能的扩展能够根据需要来动态地实现,同时可以避免扩展功能的增多导致子类数量急剧增多,从而使得任何功能扩展变化所产生的负面影响降为最低。比如,假定我们需要为游戏开发坦克,除了各种不同型号的坦克(T50T75T90)外,我们还希望在不同场合中为其增加以下一种或多种功能:

-          红外夜视功能

-          水陆两栖功能

-          卫星定位功能

如果用普通的继承的方式来增加这些功能,子类的数量将呈几何级数方式增加。这种设计思路是静态的(即通过继承的方式来获得功能的扩充),即所有可能需要用到的类,必须在代码编译之前准备好,因此,所有的子类类我们都必须编写。

 

上面所描述的问题的根源在于我们过度地使用了继承来扩展对象的功能,由于继承为类型引入的静态特质(即如前所言,必须在编译前将所有类的代码必须准备好),使得这种扩展方式缺乏灵活性;并且随着子类(各种不同型号的坦克)和扩展功能(红外、两栖和定位)的增多,各种子类和扩展功能的组合会导致子类的数量以几何级数的方式增长,以至于代码难以维护。

 

Decorator设计模式要点:

-          通过采用组合,而非继承的手法,实现了在运行时动态地扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差”和“多子类衍生问题”。

-          Component类在Decorator设计模式中充当抽象接口的角色,不应该去实现具体的行为。而且Decorator类对于Component类应该透明,即Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。

-          Decorator类在接口上表现为“is-aComponent的继承关系,即Decorator类继承了Component类所具有的接口;但在实现上又同时表现为“has-aComponent的组合关系,即Decorator类有使用了另外一个Component类。因此,我们可以使用一个或者多个Decorator对象来“装饰”一个Component对象,并且经过装饰后的对象仍然是一个Component对象。

-          Decorator设计模式并非解决“多子类衍生的多继承”问题,但它事实上大幅度减少了子类的数量,如上例中21个子类全部可以无需存在(当然增加了一个Decorator抽象类)。不过,其应用的要点在于解决“主题类在多个方向上的扩展功能”,而这正是“装饰”的含义。

 

Decorator模式可以被认为是Composite的简单版本,他们之间的不同是:

1.       Composite中有多个Component对象,而Decorator中有且仅有一个Component对象;

2.       Decorator用于增加函数的功能性,而Composite用于传递函数调用。

 

五、 Façade模式

结构型模式总结_第4张图片

A方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合,随着外部客户程序和个子系统的演化,这种过多的耦合面临很多变化的挑战。Façade设计模式则简化外部客户程序和系统间的交互接口,将外部客户程序的演化和内部子系统的变化之间的依赖相互解耦。比如,假定我们需要开发一个坦克模拟系统用于模拟坦克在各种作战环境中的行为,其中坦克系统由引擎、车轮、控制器和火炮等各子系统构成

 

“Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.” – GoF

 

Façade设计模式的几个要点:

-          从客户程序的角度来看,Façade设计模式不仅简化了整个组件系统的接口,同时对于组件内部与外部客户程序来说,从某种程度上也达到了一个“解耦”的效果 --- 内部子系统的任何变化不会影响到Façade接口的变化。

-          Façade设计模式更注重从架构的层次去看整个系统,而不是从类的层次。Façade设计模式更多的时候是一种系统架构设计模式。

 

Façade模式、Adapter模式、Bridge模式、Composite模式以及Decorator模式之间的区别:

-          Façade模式注重简化接口;

-          Adapter模式注重转换接口;

-          Bridge模式注重分离接口(抽象)与其实现;

-          Composite模式注重在稳定接口的前提下功能的自动传递;

-          Decorator模式注重在稳定接口的前提下为对象动态扩展功能。

 

六、 Flyweight模式

面向对象很好地解决了系统抽象性的问题,同时在大多数情况下,也不会损及系统的性能。但是,在某些特殊的应用中,由于对象的数量太大,采用面向对象会给系统带来难以承受的内存开销。比如图形应用中的图元等对象、字处理应用中的字符对象等等。

 

采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价---主要指内存需求方面的代价。

Flyweight(享元)设计模式可以在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作。

结构型模式总结_第5张图片 

上图中的ConcreteFlyweight对象就是可以共享的对象,是接口的具体实现,并为内部状态增加内存空间,它保存的任何状态都必须是内部(intrinsic),也就是说,ConcreteFlyweight必须和它的应用环境场合无关。

 

几乎在所有情况下,Flyweight都是一个Singleton对象。进一步地,在几乎所有的应用中,FlyweightFactory也是一个Singleton

 

七、 Proxy模式

对于复杂的软件系统常常有一种处理手法,即增加一层间接层,从而使得系统获得一种更为灵活、满足特定需求的解决方案。在面向对象的系统中,有些对象由于某种原因,比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等,直接访问会给使用者或者系统结构带来很多麻烦。

 

Proxy设计模式就是在不失去透明操作对象的同时,通过增加一层间接层来管理、控制这些对象特有的复杂性。

结构型模式总结_第6张图片

改为下图:

其中表示不同的进程

上面的图示中假定AB位于不同的进程,典型的情况是AB位于互联网上两台不同的机器上,如果A要访问B三次,那么A就要如上图调用B三次。

 

下面的图示中增加一个B的代理,该代理和A位于同一个进程内,当A要调用B的功能时,A仅需要调用B的代理即可,然后B的代理和B之间进行通信。另外如果A3次调用B的功能,那么A仅需要3此调用B的代理即可,而B的代理和B之间有可能只需要一次通信就够了,由此可见,B的代理有一定的缓冲功能。

 

“Provide a surrogate or placeholder for another object to control access to it.” -GoF

 

Proxy模式之静态结构UML类图:

结构型模式总结_第7张图片

三种不同类型的Proxy

-          Remote proxy: When you need a local representative for an object in another address space(e.g. JVM)

-          Virtual proxy: Acts as a placeholder and delays creating expensive objects.

-          Protection proxy: Determines access rights to the real object.

 

转载:http://patmusing.blog.163.com/blog/static/1358349602010150856685/

你可能感兴趣的:(设计模式,Decorator,Access,扩展,UML,interface)