Java设计模式——桥模式

Posted Q-WHai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java设计模式——桥模式相关的知识,希望对你有一定的参考价值。

概述

桥模式(Bridge)是为了解决将抽象部分与实现部分分离,好让他们都在自己的维度上有多维度地变化。这句话是好理解的,只是我在学习完桥模式之后,存在一些疑问,还好现在想通了。现在我就桥模式的设计思想和我的疑问一并发出,希望于你有益。


版权说明

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
本文作者:Coding-Naga
发表日期: 2016年3月31日
本文链接:http://blog.csdn.net/lemon_tree12138/article/details/51024127
来源:CSDN
更多内容:分类 >> 设计模式


场景

现假设市面上有多种不同型号的电视机,和一些不同的遥控器生产产商。遥控器生产产商要为这些电视机进行生产遥控器,可是这些电视机型号太多,有一些电视机的型号太杂,甚至在后期会出现一些不同型号的电视机。


普通聚合方案

在这个一般方案中,遥控器产商要为每一种电视机生产一种遥控器。类图如下
这里写图片描述
每个具体的遥控器都去继承或是实现遥控器的抽象或是接口,并且在每个具体的遥控器内部都聚合了各自的电视机接口。这种方案可以解决问题,可以解决遥控器与电视机的对应关系。可是,却有一个问题,就像上面场景中所说的,如果这里的有一些新的电视机出现,那么生产遥控器的产商还得去生产新的遥控器。这样一来各自的遥控器数量不但不好把握,而且这样的设计很繁杂。


桥模式

上面一般的聚合方案无法解决遥控器的一般性,对于新的机型无法兼容和适应。对于这样在抽象或是实现上会有多维度扩展的情况,我们就必须重新设计代码结构了。下面是桥模式,以及桥模式是如何解决这个问题的。

定义

将抽象部分(Abstraction)与实现部分(Implementor)分离,使它们可以独立地变化。

分析

桥模式的应用场景是某一个抽象或是实现可能存在多维度的变化。就像上面的遥控器实例,我们在遥控器这个抽象上,可能会有不同的生产产商;在电视机这个实现上可能会RCA、Sony等等。桥模式可以让遥控器的抽象和电视机的实现在各自的方向上多维度变化,而不用关心其他的事情。
在上面我也分析了一般的聚合方案是不可靠的,它的确可以解决一些问题,可是却是繁琐的,也是不必要的。
这里再说一个大家可能都比较熟悉的例子。比如我们现在编写的Java程序,与运行平台之间的关系。我们可以有很多很多的Java程序,而运行平台也可以是Windows、Linux或是Mac。我们的Java程序需要在所有的平台上能够执行,每一个平台也要保证能够全部的Java程序。

类图

这里我们让遥控器的抽象类聚合电视机的接口。因为所以的电视都实现电视机这个接口,那么遥控器的抽象类也就聚合了所有的电视机实现。这样不管你电视机的型号如何改变,遥控器都可以不做修改也能继续工作。
这里写图片描述
注:当时我在这里存在一个小疑问,为什么我们的电视机接口不是聚合到遥控器的子类中,而是聚合到遥控器的抽象类中呢?也就是说,这里我有没有必要有一个遥控器的抽象类?
现在我假设这里不存在这个RemoteControl的抽象类,那么ConcreteRemote将持有TV这个接口,可是这样在遥控器这个维度上都不好扩展了。桥模式的牛X之处就在于它可以让多维度的抽象和实现都可以在多维度上进行任意扩展。

逻辑实现

基于上面的类图,可编写Java代码。

TV.java

public interface TV {
    public void on();
    public void off();
    public void tuneChannel(int channel);
}

RCA.java

public class RCA implements TV {

    @Override
    public void on() {
        System.out.println("RCA被打开了");
    }

    @Override
    public void off() {
        System.out.println("RCA被关闭了");
    }

    @Override
    public void tuneChannel(int channel) {
        System.out.println("切换到第" + channel + "频道了");
    }
}

Sony.java

public class Sony implements TV {

    @Override
    public void on() {
        System.out.println("Sony被打开了");
    }

    @Override
    public void off() {
        System.out.println("Sony被打开了");
    }

    @Override
    public void tuneChannel(int channel) {
        System.out.println("切换到第" + channel + "频道了");
    }
}

RemoteControl.java

public abstract class RemoteControl {

    protected TV tv = null;
    
    public RemoteControl(TV _tv) {
        this.tv = _tv;
    }
    
    public abstract void on();
    
    public abstract void off();
    
    public void setChannel(int channel) {
        if (tv != null) {
            tv.tuneChannel(channel);
        }
    }
}

ConcreteRemote.java

public class ConcreteRemote extends RemoteControl {

    private int currentStation = 0;
    private final int MAX_STATION = 25;
    
    public ConcreteRemote(TV _tv) {
        super(_tv);
    }
    
    @Override
    public void on() {
        tv.on();
    }

    @Override
    public void off() {
        tv.off();
    }
    
    public void setChannel(int channel) {
        currentStation = channel;
        super.setChannel(currentStation);
    }
    
    public void nextChannel() {
        currentStation = (MAX_STATION + currentStation + 1) % MAX_STATION;
        super.setChannel(currentStation);
    }

    public void previousChannel() {
        currentStation = (MAX_STATION + currentStation - 1) % MAX_STATION;
        super.setChannel(currentStation);
    }
}

模式评价

优点缺点
电视机的实现被解耦,它和遥控器之间不再永久绑定相对比较复杂
遥控器和电视机可以独立扩展,且不会影响对方

Ref

  • 《Head First设计模式》

Github源码链接

https://github.com/qwhai/design-pattern


征集

如果你也需要使用ProcessOn这款在线绘图工具,可以使用如下邀请链接进行注册:
https://www.processon.com/i/56205c2ee4b0f6ed10838a6d

以上是关于Java设计模式——桥模式的主要内容,如果未能解决你的问题,请参考以下文章

C++设计模式学习笔记:Bridge 桥模式

C++设计模式学习笔记:Bridge 桥模式

java 查看寻呼机设计模式与片段。

GOF-Java基础知识和J2EE框架知识之间一座隐性的"桥"

Java二十三设计模式之-----桥接模式

你什么时候使用桥模式?它与适配器模式有何不同?