设计模式之桥接设计模式

生活中的一个例子:
    就拿电脑来说。即有华硕电脑又有神州电脑,但你也会发现,对于电脑也有不同的类型,比如,台式机,笔记本等等。在软件系统中就要适应两个方面的变化?怎样实现才能应对这种变化呢?

概述:

在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。

意图:
   将抽象部分与实现部分分离,使它们都可以独立的变化。
                                                                    ——《设计模式》GOF 
结构图:


                                 

 

桥接模式的角色和职责:

1.Client 调用端

这是Bridge模式的调用者。

2.抽象类(Abstraction)

抽象类接口(接口这货抽象类)维护队行为实现(implementation)的引用。它的角色就是桥接类。

3.Refined Abstraction

这是Abstraction的子类。

4.Implementor

行为实现类接口(Abstraction接口定义了基于Implementor接口的更高层次的操作)

5.ConcreteImplementor

Implementor的子类

传统的做法:
        通过类继承的方式来做上面的例子;
先看一下类结构图:

 缺点:
     但是我们说这样的设计是脆弱的,仔细分析就可以发现,它还是存在很多问题,首先它在遵循开放-封闭原则的同时,违背了类的单一职责原则,即一个类只有一个引起它变化的原因,而这里引起变化的原因却有两个,即品牌的变化(联想,戴尔,神州)和类型(手提,笔记本,台式)的变化;其次是重复代码会很多,再次是类的结构过于复杂,继承关系太多,难于维护,最后最致命的一点是扩展性太差。如果变化沿着电脑的品牌和不同的类型两个方向变化,我们会看到这个类的结构会迅速的变庞大。

应用设计模式:桥接设计模式

桥接模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈——换而言之两个变化不会导致纵横交错的结果,并不一定要使用桥接模式。

              

创建品牌类:

/**

* 品牌

* @author Administrator


*/

public interface Brand {

void sale();

}

class Lenovo implements Brand {

    public void sale() {

    System.out.println("销售联想电脑");

    }

}


class Dell implements Brand {

    public void sale() {
    
    System.out.println("销售Dell电脑");
    }

}

class Shenzhou implements Brand {

    public void sale() {

    System.out.println("销售神舟电脑");
    }

}

创建电脑类:


创建电脑类:

/**

* 电脑类型的维度

* @author Administrator


*/

public class Computer2 {

    protected Brand brand;
    
    public Computer2(Brand b) {

    this.brand = b;

    }


    public void sale(){

    brand.sale();
    }
}


class Desktop2 extends Computer2 {

    public Desktop2(Brand b) {
    super(b);
    }
    public void sale() {

    super.sale();
    System.out.println("销售台式机");
    
    }

}
class Laptop2 extends Computer2 {

    public Laptop2(Brand b) {
    super(b);
    }
    public void sale() {

    super.sale();
    System.out.println("销售笔记本");
    }

}

客户端调用:

public class Client {

    public static void main(String[] args) {

    //销售联想的笔记本电脑

    Computer c = new Laptop();
    
    Laptop l = new LenovoLaptop();

    c.sale();

    l.sale();

    //销售神舟的台式机

    Computer2 c2 = new Desktop2(new Shenzhou());

    c2.sale();

    }

}

效果及实现要点:
1.Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。
2.所谓抽象和实现沿着各自维度的变化,即“子类化”它们,得到各个子类之后,便可以任意它们,从而获得不同品牌的不同类型电脑。
3.Bridge模式有时候类似于多继承方案,但是多继承方案往往违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。
4.Bridge模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈——换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。

应用场景

1、如果你不希望在抽象和实现部分采用固定的绑定关系,可以采用桥接模式,来把抽象和实现部分分开,

然后在程序运行期间来动态的设置抽象部分需要用到的具体的实现,还可以动态切换具体的实现。

2、如果出现抽象部分和实现部分都应该可以扩展的情况,可以采用桥接模式,让抽象部分和实现部分可以

独立的变化,从而可以灵活的进行单独扩展,而不是搅在一起,扩展一边会影响到另一边。

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

实现部分的修改,可以独立于抽象部分,也就不会对客户产生影响了,也可以说对客户是透明的。

4、如果采用继承的实现方案,会导致产生很多子类,对于这种情况,可以考虑采用桥接模式,分析功能变

化的原因,看看是否能分离成不同的纬度,然后通过桥接模式来分离它们,从而减少子类的数目。

猜你喜欢

转载自blog.csdn.net/qq_39665334/article/details/82931906