桥接模式(GOF):指将抽象部分和实现部分分开,让它们各自随意增加减少。而不受其它约束。

     适用环境:

u       你不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。

u       类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这时Bridge模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。

u       对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。

u       C++)你想对客户完全隐藏抽象的实现部分。在C++中,类的表示在类接口中是可见的。

u       有许多类要生成。这样一种类层次结构说明你必须将一个对象分解成两个部分。Rumbaugh 称这种类层次结构为“嵌套的普化”(nested generalizations )。

u       你想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。

为什么使用?
       不希望抽象部分和行为有一种固定的绑定关系,而是应该可以动态联系的。

如果一个抽象类或接口有多个具体实现(子类、concrete subclass),这些子类之间关系可能有以下两种情况:
1. 这多个子类之间概念是并列的,如前面举例,打桩,有两个concrete class:方形桩和圆形桩;这两个形状上的桩是并列的,没有概念上的重复。

2.这多个子类之中有内容概念上重叠.那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个接口:抽象接口和行为接口,分别放置抽象和行为.

例如,一杯咖啡为例,子类实现类为四个:中杯加奶、大杯加奶、 中杯不加奶、大杯不加奶。

但是,我们注意到:上面四个子类中有概念重叠,可从另外一个角度进行考虑,这四个类实际是两个角色的组合:抽象 和行为,其中抽象为:中杯和大杯;行为为:加奶 不加奶(如加橙汁 加苹果汁).

实现四个子类在抽象和行为之间发生了固定的绑定关系,如果以后动态增加加葡萄汁的行为,就必须再增加两个类:中杯加葡萄汁和大杯加葡萄汁。显然混乱,扩展性极差。

那我们从分离抽象和行为的角度,使用Bridge模式来实现。

如何实现?
以上面提到的咖啡 为例. 我们原来打算只设计一个接口(抽象类),使用Bridge模式后,我们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口.
    先看看抽象部分的接口代码:

package bridge;
public abstract class Coffee{
    CoffeeImpl coffeeImpl
=null;
    
    
public void setCoffeeImpl(){
        
this.coffeeImpl=CoffeeImplSingleton.getCoffeeImpl();
    }

    
    
public CoffeeImpl getCoffeeImpl(){
        
return this.coffeeImpl;
    }

    
    
public abstract void  pourCoffee();
}

其中CoffeeImp 是加不加奶的行为接口,看其代码如下
package bridge;
public abstract class CoffeeImpl{
    
public abstract void pourCoffeeImpl();
}
现在我们有了两个抽象类,下面我们分别对其进行继承,实现concrete class
package bridge;
//中杯Coffee
public class MediumCoffee  extends Coffee{
    
    
public MediumCoffee (){
        setCoffeeImpl();
    }

    
    
public void pourCoffee(){
        CoffeeImpl coffeeImp
=this.getCoffeeImpl(); 
        coffeeImpl.pourCoffeeImpl();
    }

}
package bridge;
//大杯Coffee
public class SuperSizeCoffee extends Coffee{
    
public SuperSizeCoffee (){
        setCoffeeImpl();
    }

    
    
public void pourCoffee(){
        CoffeeImpl coffeeImp
=this.getCoffeeImpl(); 
        coffeeImpl.pourCoffeeImpl();
    }

}

下面对行为CoffeeImp进行继承:
package bridge;
//不加牛奶
public class FragrantCoffeeImpl extends CoffeeImpl{
    
public void pourCoffeeImpl(){
        System.out.println(
"没有加牛奶的Coffee");
    }

}
package bridge;
//加牛奶
public class CoffeeImplSingleton{
    
private static CoffeeImpl coffeeImpl;
    
public CoffeeImplSingleton(CoffeeImpl coffeeImpl){
        
this.coffeeImpl=coffeeImpl;
    }
 
    
public static CoffeeImpl getCoffeeImpl(){
        
return coffeeImpl;
    }

}

最后实现:
package bridge;
public class Bridge{
    
public static void main(String[] args){
       
       
//中杯加奶
       CoffeeImplSingleton coffeeImpl=new CoffeeImplSingleton(new MilkCoffeeImpl());
       MediumCoffee mediumCoffee 
= new MediumCoffee();
       mediumCoffee.pourCoffee();
       
       
//大杯不加奶
       CoffeeImplSingleton coffeeImpl2=new CoffeeImplSingleton(new FragrantCoffeeImpl());
       SuperSizeCoffee superSizeCoffee 
= new SuperSizeCoffee();
       superSizeCoffee.pourCoffee();

    }

}
运行结果:
加了牛奶的Coffee
没有加牛奶的Coffee
Press any key to continue...

与适配器模式的区别:桥接模式与对象形式的适配器模式很相似,然而适配器的目的是要改变已有的接口,让它们可以相容,以使没有关系的两个类能一起工作,而桥接模式是分离抽象化与实现化,以使两者的接口可以不同。因此,两模式是往两个相反方面努力的。

参考资料:
http://www.jdon.com/designpatterns/bridge.htm(本篇的主要来源)
                    
http://www.lvjiyong.com/books/DesignPatterns/20.html
                     《Java与模式》