桥接模式

转载自 http://www.javashuo.com/article/p-njknvetl-bm.htmlhtml

 

 

 在开始学java的时候老师讲到继承的时候,老是喜欢用一个例子来说解,那就是画图,这里有一个画笔,能够画正方形、长方形、圆形(这个你们都知道怎么作吧,我就不解释了)。可是如今咱们须要给这些形状进行上色,这里有三种颜色:白色、灰色、黑色。这里咱们能够画出3*3=9中图形:白色正方形、白色长方形、白色圆形。。。。。。到这里了咱们几乎到知道了这里存在两种解决方案:java

      方案一:为每种形状都提供各类颜色的版本。程序员

      方案二:根据实际须要对颜色和形状进行组合。编程

      咱们咱们采用方案一来实现的话,咱们是否是也能够这样来理解呢?为每种颜色都提供各类形状的版本呢?这个是彻底的能够的。以下:设计模式

1111

  

      对于中两个图形,咱们都会很清楚这样一个问题:加入咱们添加椭圆,咱们是否是又要增长三种颜色呢?假如咱们在增长一个绿色,咱们就要增长其四种形状了,继续加。继续加……每次增长都会增长若干个类(若是增长颜色则会增长形状个数个类,若增长形状则会增长颜色个数个类),这样的状况我想每一个程序员都不会想要吧!那么咱们看方案二。this

      方案二所提供的就是解决方法是:提供两个父类一个是颜色、一个形状,颜色父类和形状父类两个类都包含了相应的子类,而后根据须要对颜色和形状进行组合。spa

33333

 

      对于有几个变化的维度,咱们通常采用方案二来实现,这样除了减小系统中的类个数,也利于系统扩展。对于方案二的应用咱们称之为桥接模式。设计

4444

 

1、 模式定义

      桥接模式即将抽象部分与它的实现部分分离开来,使他们均可以独立变化。code

      桥接模式将继承关系转化成关联关系,它下降了类与类之间的耦合度,减小了系统中类的数量,也减小了代码量。htm

      将抽象部分与他的实现部分分离这句话不是很好理解,其实这并非将抽象类与他的派生类分离,而是抽象类和它的派生类用来实现本身的对象。这样仍是不能理解的话。咱们就先来认清什么是抽象化,什么是实现化,什么是脱耦。

      抽象化其概念是将复杂物体的一个或几个特性抽出去而只注意其余特性的行动或过程。在面向对象就是将对象共同的性质抽取出去而造成类的过程。

      实现化:针对抽象化给出的具体实现。它和抽象化是一个互逆的过程,实现化是对抽象化事物的进一步具体化。

      脱耦:脱耦就是将抽象化和实现化之间的耦合解脱开,或者说是将它们之间的强关联改换成弱关联,将两个角色之间的继承关系改成关联关系。

      对于那句话:将抽象部分与他的实现部分分离套用《大话设计模式》里面的就是实现系统可能有多个角度分类,每一种角度均可能变化,那么把这种多角度分类给分离出来让他们独立变化,减小他们之间耦合。

      桥接模式中的所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用关联关系(组合或者聚合关系)而不是继承关系,从而使二者能够相对独立地变化,这就是桥接模式的用意。

2、 模式结构

      下图是桥接模式的UML结构图:

 

55555

 

      桥接模式主要包含以下几个角色:

      Abstraction:抽象类。 
      RefinedAbstraction:扩充抽象类。 
      Implementor:实现类接口。 
      ConcreteImplementor:具体实现类
 。 

3、 模式实现

      模式场景咱们就采用哪一个画图的。其UML结构图以下:

66666

      首先是形状类:该类为一个抽象类,主要提供画形状的方法:Shape.java

复制代码
public abstract class Shape {
    Color color;

    public void setColor(Color color) {
        this.color = color;
    }
    
    public abstract void draw();
}
复制代码

      而后是三个形状 。圆形:Circle.java

复制代码
public class Circle extends Shape{

    public void draw() {
        color.bepaint("正方形");
    }
}
复制代码

      长方形:Rectangle.java

复制代码
public class Rectangle extends Shape{

    public void draw() {
        color.bepaint("长方形");
    }

}
复制代码

      正方形:Square.java

复制代码
public class Square extends Shape{

    public void draw() {
        color.bepaint("正方形");
    }

}
复制代码

      颜色接口:Color.java

public interface Color {
    public void bepaint(String shape);
}

      白色:White.java

复制代码
public class White implements Color{

    public void bepaint(String shape) {
        System.out.println("白色的" + shape);
    }

}
复制代码

      灰色:Gray.java

复制代码
public class Gray implements Color{

    public void bepaint(String shape) {
        System.out.println("灰色的" + shape);
    }
}
复制代码

      黑色:Black.java

复制代码
public class Black implements Color{

    public void bepaint(String shape) {
        System.out.println("黑色的" + shape);
    }
}
复制代码

      客户端:Client.java

复制代码
public class Client {
    public static void main(String[] args) {
        //白色
        Color white = new White();
        //正方形
        Shape square = new Square();
        //白色的正方形
        square.setColor(white);
        square.draw();
        
        //长方形
        Shape rectange = new Rectangle();
        rectange.setColor(white);
        rectange.draw();
    }
}
复制代码

      运行结果:

      白色的正方形 
      白色的长方形

4、 模式优缺点

优势

      一、分离抽象接口及其实现部分。提升了比继承更好的解决方案。

      二、桥接模式提升了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不须要修改原有系统。

      三、实现细节对客户透明,能够对用户隐藏实现细节。

缺点

      一、桥接模式的引入会增长系统的理解与设计难度,因为聚合关联关系创建在抽象层,要求开发者针对抽象进行设计与编程。 
      二、桥接模式要求正确识别出系统中两个独立变化的维度,所以其使用范围具备必定的局限性。

5、 模式使用场景

       一、若是一个系统须要在构件的抽象化角色和具体化角色之间增长更多的灵活性,避免在两个层次之间创建静态的继承联系,经过桥接模式可使它们在抽象层创建一个关联关系。

       二、对于那些不但愿使用继承或由于多层次继承致使系统类的个数急剧增长的系统,桥接模式尤其适用。

       三、一个类存在两个独立变化的维度,且这两个维度都须要进行扩展。

6、 模式总结

      一、桥接模式实现了抽象化与实现化的脱耦。他们两个互相独立,不会影响到对方。

      二、对于两个独立变化的维度,使用桥接模式再适合不过了。

      三、对于“具体的抽象类”所作的改变,是不会影响到客户。