结构型设计模式总结(上)

来源:互联网 发布:网页优化方案 编辑:程序博客网 时间:2024/05/20 18:20

 Adapter适配器:

“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。

将一个类的接口转换成客户希望的另一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可

以一起工作。

对象适配器:对象组合方式,松耦合
类适配器:采用多继承实现,用的少

Adapter模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用

,类库迁移等方面非常有用。

Adapter模式本身要求我们尽可能使用“面向接口的编程”,这样才能在后期很方便地适配。

Bridge桥:
例子:我们需要开发一个同时支持PC和手机的坦克游戏,游戏在PC和手机上功能都一样,都有同样的类型,面临同样的功能需求变化,比如坦克可能有多种不同的型号:T50,T75.....对于其中的坦克设计,我们可能很容易设

计出一个Tank的抽象基类,然后各种不同型号的Tank继承自该类。但是PC和手机的图像绘制、声效、操作等实现完全不同...因此对于各种型号的坦克,都要提供各种不同平台上的坦克实现。这样的设计会带来很多问题:有很多

重复的代码,类的结构过于复杂,难以维护,最致命的是引入任何新平台,比如TV,都会让整个类层级结构复杂化


问题的症结:事实上由于Tank类型具有两个变化的维度:

“平台的变化”,“型号的变化”。
如何应对“对维度的变化”。

Bridge意图:将抽象部分与实现(也可以是抽象)部分分离,使它们都可以独立化。---“多个维度的变化”的分离

采用对象组合方式。(多继承也可以实现这个功能,但这样就变得“紧耦合”)
使得“平台”,“型号”维度独立变化,然后可以任意组合它们,从而获得不同平台下的不同型号。

Bridge模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并

不剧烈---换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。

Composite组合:
一类具有“容器”特征的对象--即它们在充当对象的时候,又是其他对象的容器。

这时客户必须知道这个“容器”的结构,并进行复杂的递归操作。

上述描述的问题的根源在于:客户代码过多依赖于对象容器复杂的内部实现结构,对象容器内部实现结构(而非抽

象接口)的变化将引起客户代码的频繁变化,带来了代码的维护性、扩展性等弊端。

意图:将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使

用具有一致性。(复杂结构操作在对象自身内部就实现,只给外部客户提供一个简单的接口)

Decorator装饰:
例子:假如我们需要为游戏中开发一种坦克,除了各种型号的坦克外,我们还希望在不同场合中为其增加一下一种

或者多种功能,比如红外线夜视功能,水陆两栖功能,卫星定位等等。

常规做法:
//抽象坦克
public abstract class Tank{}
//各种型号
public class T50:Tank{}
public class T75:Tank{}
public class T80:Tank{}
//各种不同功能组合
public class T50A:T50,IA{}
public class T50B:T50,IB{}
public class T75AB:T75,IA,IB{}
......
上述问题在于我们“过度使用了继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺

乏灵活性,并随着子类的增多(加一个功能,就加一个子类),各种功能的组合会导致更多子类的膨胀。

如何使“对象功能的扩展”能够根据需要来动态地实现(运行时)?同时避免子类膨胀问题?从而使得任何“功能

扩展变化”所导致的影响降为最低?

Decorator意图:动态地给一个对象增加一些额外的职责(功能)。

public abstract Tank{}
public abstract T50:Tank{}
public Decorator:Tank{调用Tank的函数功能}

//不是is a的关系,在实现表现为Has a的组合关系
//功能
public DecoratorA:Decorator{构造函数中传入Tank类型

}
public DecoratorB:Decorator{构造函数中传入Tank类型

}
public DecoratorC:Decorator{构造函数中传入Tank类型

}

class App
{Tank tank50= new T50();
DecoratorA da=new DecoratorA(tank50);
DecoratorC da=new DecoratorC(tank50);
Tank tank75= new T75();
DecoratorA da=new DecoratorA(tank75);
DecoratorC da=new DecoratorC(tank75);//这样就可以

随意的扩展。
}

Decorator模式并非解决“多子类衍生的多继承”问题,而在于解决“主体类在多个方向上的扩展功能”---这就

是装饰的含义。

Facade外观:
如何简化外部客户程序和系统间的交互接口?如何将外部客户程序的演化和内部子系统的变化之间的依赖相互解耦


Facade意图:为子系统的一组接口提供一个一致的界面,

Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

要点:
1.不仅简化了整个组件系统的接口,同时对于组件内部与外部客户程序来说,从某种成都上也达到了一种“解耦”

的效果---内部子系统的任何变化不会影响到Facade接口的变化。
2.Facade设计模式更注重从架构的层次去看整个系统,而不是单个类的层次,Facade很多时候更是一种架构设计模式。
3.Facade模式注重简化接口,Adapter模式注重转换接口,Bridge模式注重分离接口(抽象)与实现,Decorator模

式注重稳定接口的前提下为对象扩展功能。


Flyweight享元(用得少):
采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价---主要指向内

存需求方面的代价。
如何在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作?

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

Flyweight模式主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。
Flyweight采用共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。

Proxy代理:
有些对象由于某种原因(比如对象创建的开销大,或者某些操作需要安全控制,或者需要进程外的访问等),直接

访问会给使用者、或者系统结构带来很多麻烦。
如何在不失去透明操作对象的同时来管理、控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决

方式。
Proxy意图:为其他对象提供一种代理以控制对这个对象的访问。

 

结构型设模式总结:
Adapter模式注重转换接口,将不吻合的接口匹配对象。


Bridge模式注重分离接口与其实现,支持多维度变化。(接口可能也不稳定)


Composite模式注重统一接口,将“一对多”的关系转化为“一对一”的关系。(容器,结构复杂)


Decorator模式注重稳定接口,在此前提下为对象扩展功能。


Facade模式注重简化剪口,简化组件系统与外部客户程序的依赖关系。


FlyWeight模式注重保留接口,在内部使用共享技术对对象存储进行优化。


Proxy模式注重假借接口,增加间接层来实现灵活控制。

原创粉丝点击