大话设计模式—桥接模式

桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。主要解决:在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。

大话设计模式中程杰老师给出的定义是,桥接模式:将抽象部分与实现部分分离,使它们都可以独立的变化

首先我们来看一个问题:现在我有一个N品牌一个M品牌的手机,两个品牌的手机都有两种功能:游戏和通讯录,我们该如何实现?

依据面向对象的理论设计,我们有两种设计思想:

实现一:先有一个品牌,多个品牌就抽象出一个品牌抽象类,对于每个功能,就都继承各自的品牌;

大话设计模式—桥接模式_第1张图片

实现二:先有功能,多个功能就可以抽象出一个抽象功能类,对于每个手机品牌,分别去继承各个功能;

大话设计模式—桥接模式_第2张图片

上面的设计完美的遵循了面向对象的原则,但是,问题也随之而来,如果我现在需要给每个品牌都增加一个MP3播放器功能,我们该怎么办?

对于实现一,我们需要在每个品牌下面分别增加一个MP3播放器功能;对于实现二,我们需要在手机软件下增加一个抽象的MP3播放器功能,然后各个手机品牌再分别去继承这个功能。

如果我们需要再增加一个手机品牌呢?那我们要改动的地方就越来越多了。显然这种设计似乎有问题的。

但我们学会使用面向对象的继承时,确实感觉它非常强大,但是并不是所有的情况都可以使用面向对象的继承,而且有很多情况下,使用继承会带来麻烦。比如,对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化都必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其它更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。

就像我们上面的两种实现,如果不断地增加新的手机品牌和功能,类会越来越多。怎么解决呢?面向对象设计中还有一个很重要的原则合成/聚合复用原则,即优先使用对象合成/聚合,而不是类继承

合成表示一种强的拥有关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样,打个比方:人有两个胳膊,胳膊和人就是部分和整体的关系,人去世了,那么胳膊也就没用了,也就是说胳膊和人的生命周期是相同的,合成关系用实心的菱形+实线来表示。

合成/聚合复用规则的好处:优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持在一个较小的规模,并且不太可能增长为不可控制的庞然大物。

下面我么来看看遵循合成/聚合复用规则的实现三:

大话设计模式—桥接模式_第3张图片

桥接模式的核心意图就是把这些实现独立出来,让它们各自的变化。这就使得每种实现的变化不会影响其它的实现,从而达到应对变化的目的。

大话设计模式—桥接模式_第4张图片

代码实现:

package com.bridge;

public abstract class Implementor {

    public abstract void operation();

}
package com.bridge;

public class ConcreteImplementorA extends Implementor {

    @Override
    public void operation() {
        System.out.println("具体实现A执行");
    }

}
package com.bridge;

public class ConcreteImplementorB extends Implementor {

    @Override
    public void operation() {
        System.out.println("具体实现B执行");
    }

}
package com.bridge;

public abstract class Abstraction {

    protected Implementor implementor;

    public void setImplementor(Implementor implementor){
        this.implementor = implementor;
    }

    public void operation(){
        implementor.operation();
    }

}
package com.bridge;

public class RefinedAbstraction extends Abstraction {

    public void operation(){
        implementor.operation();
    }

}
package com.bridge;

public class BridgePatternDemo {

    public static void main(String[] args) {

        Abstraction ab = new RefinedAbstraction();

        ab.setImplementor(new ConcreteImplementorA());
        ab.operation();

        ab.setImplementor(new ConcreteImplementorB());
        ab.operation();
    }

}

运行结果:

具体实现A执行
具体实现B执行

应用实例: 墙上的开关,可以看到的开关是抽象的,不用管里面具体怎么实现的。

优点:

1、抽象和实现的分离。
2、优秀的扩展能力。
3、实现细节对客户透明。

缺点

桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。

使用场景:

1、如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。

2、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。

3、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展,对于两个独立变化的维度,使用桥接模式再适合不过了。

你可能感兴趣的:(设计模式,继承,桥接模式,bridge,合成聚合)