《Head First 设计模式》笔记16-桥接模式

  1. 定义
  2. 模式结构
  3. 示例代码
  4. 桥接模式与策略模式
  5. 优缺点
  6. 参考

定义

桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。

使用桥接模式(Bridge Pattern)不只改变你的实现,也改变你的抽象。

设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案:

  • 第一种设计方案是为每一种形状都提供一套各种颜色的版本。
  • 第二种设计方案是根据实际需要对形状和颜色进行组合

对于有两个变化维度(即两个变化的原因)的系统,采用方案二来进行设计系统中类的个数更少,且系统扩展更为方便。设计方案二即是桥接模式的应用。桥接模式将继承关系转换为关联关系,从而降低了类与类之间的耦合,减少了代码编写量。

有了桥接模式,就可以独立地改变这两个层次。

模式结构

桥接模式包含如下角色:

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

示例代码

首先定义电视机的接口:ITV

public interface ITV {
    public void on();
    public void off();
    public void switchChannel(int channel);
}

实现三星的 ITV 接口。

public class SamsungTV implements ITV {
    @Override
    public void on() {
        System.out.println("Samsung is turned on.");
    }

    @Override
    public void off() {
        System.out.println("Samsung is turned off.");
    }

    @Override
    public void switchChannel(int channel) {
        System.out.println("Samsung: channel - " + channel);
    }
}

再实现索尼的 ITV 接口。

public class SonyTV implements ITV {

    @Override
    public void on() {
        System.out.println("Sony is turned on.");
    }

    @Override
    public void off() {
        System.out.println("Sony is turned off.");
    }

    @Override
    public void switchChannel(int channel) {
        System.out.println("Sony: channel - " + channel);
    }
}

遥控器要包含对 TV 的引用。

public abstract class AbstractRemoteControl {
    /**
     * @uml.property  name="tv"
     * @uml.associationEnd
     */
    private ITV tv;

    public AbstractRemoteControl(ITV tv){
        this.tv = tv;
    }

    public void turnOn(){
        tv.on();
    }

    public void turnOff(){
        tv.off();
    }

    public void setChannel(int channel){
        tv.switchChannel(channel);
    }
}

定义遥控器的具体类。

public class LogitechRemoteControl extends AbstractRemoteControl {

    public LogitechRemoteControl(ITV tv) {
        super(tv);
    }

    public void setChannelKeyboard(int channel){
        setChannel(channel);
        System.out.println("Logitech use keyword to set channel.");
    }

    public static void main(String[] args){
        ITV tv = new SonyTV();
        LogitechRemoteControl lrc = new LogitechRemoteControl(tv);
        lrc.setChannelKeyboard(100);
    }
}

输出如下:

Sony: channel – 100
Logitech use keyword to set channel.

桥接模式与策略模式

  1. 首先,在形式上,两者还是有一定区别的,对比两幅结构图,我们可以发现,在桥接模式中不仅 Implementor 具有变化(ConcreateImplementior),而且 Abstraction 也可以发生变化(RefinedAbstraction),而且两者的变化是完全独立的,RefinedAbstraction 与 ConcreateImplementior 之间松散耦合,它们仅仅通过 Abstraction 与 Implementor 之间的关系联系起来。而在策略模式中,并不考虑 Context 的变化,只有算法的可替代性。

  2. 其次在语意上,桥接模式强调 Implementor 接口仅提供基本操作,而 Abstraction 则基于这些基本操作定义更高层次的操作。而策略模式强调 Strategy 抽象接口的提供的是一种算法,一般是无状态、无数据的,而 Context 则简单调用这些算法完成其操作。

  3. 桥接模式中不仅定义 Implementor 的接口而且定义 Abstraction 的接口,Abstraction 的接口不仅仅是为了与 Implementor 通信而存在的,这也反映了结构型模式的特点:通过继承、聚合的方式组合类和对象以形成更大的结构。在策略模式中,Startegy 和 Context 的接口都是两者之间的协作接口,并不涉及到其它的功能接口,所以它是行为模式的一种。行为模式的主要特点就是处理的是对象之间的通信方式,往往是通过引入中介者对象将通信双方解耦,在这里实际上就是将 Context 与实际的算法提供者解耦。

所以相对策略模式,桥接模式要表达的内容要更多,结构也更加复杂。桥接模式表达的主要意义其实是接口隔离的原则,即把本质上并不内聚的两种体系区别开来,使得它们可以松散的组合,而策略在解耦上还仅仅是某一个算法的层次,没有到体系这一层次。从结构图中可以看到,策略的结构是包容在桥接结构中的,桥接中必然存在着策略模式,Abstraction 与 Implementor 之间就可以认为是策略模式,但是桥接模式一般 Implementor 将提供一系列的成体系的操作,而且 Implementor 是具有状态和数据的静态结构。而且桥接模式 Abstraction 也可以独立变化。

优缺点

桥接模式的优点:

  • 分离抽象接口及其实现部分。
  • 桥接模式有时类似于多继承方案,但是多继承方案违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差,而且多继承结构中类的个数非常庞大,桥接模式是比多继承方案更好的解决方法。
  • 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。
  • 实现细节对客户透明,可以对用户隐藏实现细节。

桥接模式的缺点:

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

参考

http://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/bridge.html
http://www.importnew.com/6857.html
http://www.blogjava.net/wangle/archive/2007/04/25/113545.html


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com

文章标题:《Head First 设计模式》笔记16-桥接模式

文章字数:1.5k

本文作者:Bin

发布时间:2018-08-01, 13:17:57

最后更新:2019-08-06, 00:07:35

原始链接:http://coolview.github.io/2018/08/01/Head-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E3%80%8AHead-First-%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E3%80%8B%E7%AC%94%E8%AE%B016-%E6%A1%A5%E6%8E%A5%E6%A8%A1%E5%BC%8F/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录