设计模式-结构型

575 阅读8分钟

七、外观模式(Facade)

1、定义

为子系统的一组接口提供一个一致的界面,定义了一个高层接口,这个接口使得这一子系统更容易使用。

2、类图

3、调用顺序

4、代码示例

5、何时选用外观模式

1、如果你希望为一个复杂的子系统提供一个简单接口的时候

2、如果想要让客户程序和抽象类的实现部分松散耦合

3、如果构建多层结构的系统

八、适配器(Adapter)

1、定义

将一个类的接口转换成 客户希望的另外一个接口。使得原本由于接口不兼容的类可以一起工作。

2、类图

Client:客户端,调用自己需要的领域接口Target。

Target:定义客户端需要的跟特定领域相关的接口。

Adaptee:已经存在的接口,通常能满足客户端的功能要求,但是接口与客户端要求的特定领域接口不一致,需要被适配。

Adapter:适配器,把Adaptee适配成为Client需要的Target。

3、代码示例

4、何时选用适配器模式

1、如果你想要使用一个已经存在的类,但是它的接口不符合你的需求

2、如果你想创建一个可以复用的类,这个类可能和一些不兼容的类一起工作

3、如果你想使用一些已经存在的子类,但是不可能对每一个子类都进行适配

九、桥接模式(Bridge)

1、定义

将抽象部分与它的实现部分分离,使它们都可以独立地变化。

2、类图

Abstraction:抽象部分的接口。通常在这个对象里面,要维护一个实现部分的对象引用,在抽象对象里面的方法,需要调用实现部分的对象来完成。这个对象里面的方法,通常都是跟具体的业务相关的方法。

RefinedAbstraction:扩展抽象部分的接口,通常在这些对象里面,定义跟实际业务相关的方法,这些方法的实现通常会使用Abstraction中定义的方法,也可能需要调用实现部分的对象来完成。

Implementor:定义实现部分的接口,这个接口不用和Abstraction里面的方法一致,通常是由Implementor接口提供基本的操作,而Abstraction里面定义的是基于这些基本操作的业务方法,也就是说Abstraction定义了基于这些基本操作的较高层次的操作。

ConcreteImplementor:真正实现Implementor接口的对象。

3、调用顺序

4、示例代码

5、何时选用桥接模式

1、如果你不希望在抽象和实现部分采用固定的绑定关系,可以采用桥接模式,来把抽象和实现部分分开,然后在程序运行期间来动态的设置抽象部分需要用到的具体的实现,还可以动态切换具体的实现。

2、如果出现抽象部分和实现部分都应该可以扩展的情况,可以采用桥接模式,让抽象部分和实现部分可以独立的变化,从而可以灵活的进行单独扩展,而不是搅在一起,扩展一边会影响到另一边。

3、如果希望实现部分的修改,不会对客户产生影响,可以采用桥接模式,客户是面向抽象的接口在运行,实现部分的修改,可以独立于抽象部分,也就不会对客户产生影响了,也可以说对客户是透明的。

4、如果采用继承的实现方案,会导致产生很多子类,对于这种情况,可以考虑采用桥接模式,分析功能变化的原因,看看是否能分离成不同的纬度,然后通过桥接模式来分离它们,从而减少子类的数目

十、组合模式(Composite)

1、定义

将对象组合成属性结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对用的使用具有一致性。

2、类图

Component:抽象的组件对象,为组合中的对象声明接口,让客户端可以通过这个接口来访问和管理整个对象结构,可以在里面为定义的功能提供缺省的实现。

Leaf:叶子节点对象,定义和实现叶子对象的行为,不再包含其它的子节点对象。

Composite:组合对象,通常会存储子组件,定义包含子组件的那些组件的行为,并实现在组件接口中定义的与子组件有关的操作。

Client:客户端,通过组件接口来操作组合结构里面的组件对象。

3、示例代码

4、何时选用组合模式

1、如果你想表示对象的部分-整体层次结构,可以选用组合模式,把整体和部分的操作统一起来,使得层次结构实现更简单,从外部来使用这个层次结构也简单;

2、如果你希望统一的使用组合结构中的所有对象,可以选用组合模式,这正是组合模式提供的主要功能;

十一装饰者(Decorator)

1、定义

动态的给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更灵活。

2、类图

Component:组件对象的接口,可以给这些对象动态的添加职责。 ConcreteComponent:具体的组件对象,实现组件对象接口,通常就是被装饰器装饰的原始对象,也就是可以给这个对象添加职责。

Decorator:所有装饰器的抽象父类,需要定义一个与组件接口一致的接口,并持有一个Component对象,其实就是持有一个被装饰的对象。注意,这个被装饰的对象不一定是最原始的那个对象了,也可能是被其它装饰器装饰过后的对象,反正都是实现的同一个接口,也就是同一类型。

ConcreteDecorator:实际的装饰器对象,实现具体要向被装饰对象添加的功能。

3、示例代码

4、何时选用装饰模式

1、如果需要在不影响其它对象的情况下,以动态、透明的方式给对象添加职责

2、如果不合适使用子类来进行扩展的时候

十二、享元模式(Flyweight)

1、定义

运用共享技术有效地支持大量细粒度的对象。

2、类图

Flyweight:享元接口,通过这个接口flyweight可以接受并作用于外部状态。通过这个接口传入外部的状态,在享元对象的方法处理中可能会使用这些外部的数据。

ConcreteFlyweight:具体的享元实现对象,必须是可共享的,需要封装flyweight的内部状态。

UnsharedConcreteFlyweight:非共享的享元实现对象,并不是所有的Flyweight实现对象都需要共享。非共享的享元实现对象通常是对共享享元对象的组合对象。

FlyweightFactory:享元工厂,主要用来创建并管理共享的享元对象,并对外提供访问共享享元的接口。

Client:享元客户端,主要的工作是维持一个对flyweight的引用,计算或存储享元对象的外部状态,当然这里可以访问共享和不共享的flyweight对象。

3、调用顺序

4、示例代码

5、何时选用享元模式

1、如果一个应用程序使用了大量的细粒度对象,可以使用享元模式来减少对象数量;

2、如果由于使用大量的对象,造成很大的存储开销,可以使用享元模式来减少对象数量,并节约内存;

如果对象的大多数状态都可以转变为外部状态,比如通过计算得到,或是从外部传入等,可以使用享元模式来实现内部状态和外部状态的分离如果不考虑对象的外部状态,可以用相对较少的共享对象取代很多组合对象,可以使用享元模式来共享对象,然后组合对象来使用这些共享对象;

十三、代理模式(Proxy)

1、定义

为其他对象提供一种代理以控制对这个对象的访问。

2、类图

Proxy:代理对象,通常具有如下功能:

  1. 实现与具体的目标对象一样的接口,这样就可以使用代理来代替具体的目标对象

  2. 保存一个指向具体目标对象的引用,可以在需要的时候调用具体的目标对象,可以控制对具体目标对象的访问,并可能负责创建和删除它

Subject:目标接口,定义代理和具体目标对象的接口,这样就可以在任何使用具体目标对象的地方使用代理对象

RealSubject:具体的目标对象,真正实现目标接口要求的功能。

3、调用顺序

4、示例代码

5、何时选用代理模式

需要为一个对象在不同的地址空间提供局部代表的时候,可以使用远程代理;

需要按照需要创建开销很大的对象的时候,可以使用虚代理;

需要控制对原始对象的访问的时候,可以使用保护代理;

需要在访问对象的时候执行一些附加操作的时候,可以使用智能指引代理;