桥梁模式

                                            桥梁模式

桥梁模式是一个使用次数比较少的设计模式,但是熟悉这个设计模式对于理解面向对象的设计原则,包括开-闭原则以及组合聚合复用原则都很有帮助。理解这两个原则,有助于形成正确的设计思想和培养良好的设计风格。
桥梁模式的用意
    桥梁模式的用意是将抽象化(Abstraction)和实现化(Implementation)脱耦,使得二者可以独立地变化。


实现化
   抽象化给出具体的实现,就是实现化。
   一个类的实例就是这个类的实现化,一个具体子类是它的抽象超类的实现化。在更加复杂的情况下,实现化也可以是与抽象化等级结构相平行的等级结构,同样可以由抽象类和具体类组成。


抽象化
    存在于多个实体中的共同的概念性联系,就是抽象化。作为一个过程,抽象化就是忽略一些信息,从而把不同的实体当做同样的实体来对待。
    通常情况下,一组对象如果具有相同的概念性联系,那么它们就可以通过一个共同的类来描述。如果一些类具有相同的概念行联系,往往可以通过一个共同的抽象类来描述。在更加复杂的情况下,可以使用一个继承关系的包括抽象类和具体子类的等级结构来描述。

脱耦
   
所谓耦合,就是两个实体的行为的某种强关联。将它们的强关联去掉就是耦合的解脱,或称脱耦。在这里,脱耦是指将抽象化和实体化之间的耦合解脱开,或者说是将它们之间的强关联改换成弱关联。

   所谓强关联,就是在编译时期已经确定,无法在运行时期动态改变的关联;所谓弱关联,就是可以动态地确认并且可以在运行时期动态地改变的关联。显然,在java语言中,继承关系是强关联,聚合关系是弱关联。

   将两个角色之间的继承关系改为聚合关系,就是将它们之间的强关联改换成为弱关联。因此,桥梁模式中所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以相对独立变化。这就是桥梁模式的用意。

继承关系及其缺点

    对数据的抽象化、继承关系、封装和多态性并称java和其他面向对象语言的几大特征。

    在面向对象的系统设计中,抽象和实现是常见的强有力的武器,也是实现“开-闭原则”的重要武器。一般而言,由java接口或者java抽象类构成抽象角色;而由一个或者多个java具体类实现抽象角色所声明的接口,以提供几种不同的实现。比如“马”是一个抽象角色,而“白马”和“黑马”都是具体角色,如下图:

                               桥梁模式
    这种看上去似乎是天经地义的套路,其实有不可避免的缺点,即灵活性不够。继承是一种强耦合,它在一开始便把抽象化角色和实现化角色的关系绑定(binding),使得两个层次相互限制,无法独立地演化。

    桥梁模式提供了这样一种用聚合关系实现的弱耦合解决方案。

              桥梁模式的结构

    桥梁模式是对象的结构模式,又称为柄体(Handle and Body)模式或者接口Interface)模式。


类图与角色
   
下图所示就是一个实现了桥梁模式的示意性系统的结构图:

            桥梁模式         
    可以看出,这个系统包含有两个等级结构,也就是:
   (1)由抽象化角色和修正抽象化角色组成的抽象化等级结构。
   (2)由实现化角色和两个具体实现化角色所组成的实现化等级结构。
    桥梁模式所涉及的角色:
    1.抽象化(Abstraction)角色:抽象化给出的定义,并保存一个队实现化对象的引用。
    2.修成抽象化(Refined Abstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。
    3.实现化(Implementor)角色:这个角色给出实现化角色的接口,但不给出具体的实现。必须指出的是,这个接口不一定和抽象化角色的接口定义相同,实际上,这两个接口可以非常不一样。实现化角色应当只给出底层操作,而抽象化角色应当只给出基于底层操作更高一层的操作。

    4.具体实现化(Refined Implementor)角色:这个角色给出实现化角色接口的具体实现。

    抽象化角色就像是一个水杯的手柄,而实现化角色和具体实现化角色就像是水杯的杯身。手柄控制杯身,这就是次模式名“柄体模式”的来源。对象是对行为的封装,而行为是由方法实现的。



源代码如下:

抽象化角色: Abstraction.java

package com.pattem.bridge;

/**
 * 抽象化角色
 * */
public abstract class Abstraction {
	
	protected Implementor imp;
	public Abstraction(Implementor imp){
		this.imp = imp;
	}
	
	//示例方法
	public void operation(){
		imp.operationImp();
	}

}



修正抽象化角色:RefineAbstraction.java

package com.pattem.bridge;

/**
 * 修正抽象化角色
 * */
public class RefineAbstraction extends Abstraction{
	

	public RefineAbstraction(Implementor imp) {
		super(imp);
	}

	public void operation(){
		//商业方法逻辑
		System.out.println("this is the refine abstract role");
	}
}

实现化角色:Implementor.java

package com.pattem.bridge;

/**
 * 实现化角色
 * */
public abstract class Implementor {

	
	//商业方法的实现化声明
	public abstract void operationImp();
}











具体实现化角色:ConcreteImplementorA.java

package com.pattem.bridge;

/**
 * 具体实现化角色 
 * */
public class ConcreteImplementorA extends Implementor {

	//商业方法的实现化实现
	public void operationImp() {
		System.out.println("this is the business concrete implement method");
	}

}


                                  桥梁模式和其他模式的关系
桥梁模式和适配器模式的区别

     
对象形式的适配器模式可能看上去很像适配器模式。然而适配器模式的目的是要改变已有的接口,让它可以相容,以便使没有关系的两个类能在一起工作。而桥梁模式是分离抽象化和实现化,使得两者之间的接口以不同。因此两个模式是向相反的方向努力的。
桥梁模式和策略模式的区别

     
区别类图相似而本质不同的设计模式的关键是比较两者的用意:一个模式被设计出来要解决的问题就是模式的用意。策略模式常常和桥梁模式混淆。尽管两者看上去很像,但它们是用来解决完全不同的设计问题。策略模式是关于计算方法的封装的,而桥梁模式是关于怎么把抽象化角色和实现化角色的强耦合解除的。桥梁式的目的是要为同一个抽象化角色提供不同的实现。
桥梁模式和装饰模式的关系     

      桥梁模式和装饰模式的用意确有相似之处,它们都要避免太多的子类。如果有两个基类,它们各有很多子类,怎么划分这些类使得客户端需要尽量少的子类?

     装饰模式的办法是把每个子类中比基类多出来的行为放到单独的类里面。这样当这些描述额外行为的对象被封装到基类对象里面时,就得到了所需要的子类对象。将这些描述额外行为的类,排列组合可以造出很多的功能组合来。如果用静态继承的方法创建这些组合出来的类所涉及到的工作量很大,以致实际上很难做到。饰模式要求所有的这些“额外行为类”具有相同的接口。

      桥梁模式的解决办法则又有所不同,桥梁模式把原来的两个基类的实现化细节抽出来,在建造到一个实现化的等级结构中,然后再把原有的基类改造成一个抽象化等级结构。

     桥梁模式中抽象化角色里面的子类不能像装饰模式那样嵌套,桥梁模式却可以连续使用。换而言之,一桥梁模式的实现化角色可以成为下一步桥梁模式的抽象化角色。

桥梁模式与状态模式的关系

     
桥梁模式描述两个等级结构之间的关系,状态模式则描述一个对象与其(外部化的)状态对象之间的系。
显然,状态对象可以看做是桥梁模式的一个退化后的特殊情况,而在使用状态模式的系统中,类型与子类型的变化会使得系统向桥梁模式演化。

桥梁模式与抽象工厂模式的关系

      
桥梁模式的设计会涉及到多个等级结构的处理,而抽象工厂模式也要涉及到多个等级结构的问题。

      在抽象工厂模式中,产品可以按照等级结构和产品族来分类。等级结构是静态的关系,处于同一个等级结构中的产品之间的关系是静态的关系;而产品族是动态的关系,系统使用哪一个产品族的产是可以在运行时期决定的。这就是两个模式的相似之处。

      抽象工厂模式中的工厂等级结构与产品等级结构没有哪一个是抽象化,哪一个是实现化的分别;相反后者它们的前者是后者的创建者。因此抽象工厂模式可以为桥梁模式提供产品创建的结构。

      


                                                  桥梁模式的实现

实现化角色的退化

      
在只有一个具体实现化角色的情况下,抽象化的实现化角色就没有意义了,不如取消掉,如下图所示。但是抽象化角色与实现化角色的划分仍然有意义。比如,如果实现化角色发生改变,则只需要把抽象化角色重新连接到新的实现化角色即可,而不必重新编译客户端。这在一些分散在不同地理位置的系统里,客户端不宜经常改变的情况下是非常有用的。

                           桥梁模式

        当具体实现化类只有一个Concretelmplementor的情况下,抽象实现化类就可以省略了。

抽象化角色的行为

     
在很多情况下,Abstraction和RefinedAbstraction并没有区别。换而言之,修正抽象化角色没有“修正”抽象化角色的行为,这是当然允许的情况。

多个实现类的情况

     
当有多于一个实现类时,应当在什么地方、什么时候、怎么创建一个实现类的实例呢?
      如果抽象化角色知道具体实现化角色的所有信息,那么它可以在构造子里根据传进的参数来决定创建哪一个具体实现化角色类的实例。

     另一个可以采用的方法是,先选用一个具体实现化角色类进行实例化,然后再根据情况改为另一个具体实现层类的实例。比如在读取输入数据时,可以根据使用频率的上升幅度临时决定改用一个对大量数据处理比较合适的实现化角色类。

共享具体实现化角色

      可以有几个抽象化角色类合用相同的具体实现化角色类。既然抽象与实现已经分离,那么当然会有几个不同的抽象化共享相同实现的情况,这也是本模式的优越性所在。



                                          在什么情况下应当使用桥梁模式

     
(1)如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的联系。

     (2)设计要求实现化角色的任何改变不应当影响客户端,或者说实现化角色的改变对客户端是完全透明的。

     (3)一个构件有多于一个的抽象化角色和实现化角色,系统需要他们之间进行动态耦合。

     (4)虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。




 


 


 

 

你可能感兴趣的:(桥梁模式)