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/William-Hai/DesignPattern-Bridge2


时间: 2024-10-29 19:08:46

Java设计模式——桥模式的相关文章

Java 设计模式 -- 复合模式之二

接着上文的鸭鸣例子:Java 设计模式 -- 复合模式之一 上文中,我们的鸭鸣实现了 装饰者模式  适配器模式  工厂模式的结合 现在,又需要进行改动了,上文,是可以统计一群鸭子的叫声,现在需要能够观察个别鸭子的行为 引入观察者模式: 任何想被观察的Quackable都必须实现下面的接口 public interface QuackObservable { public void registerObserver(Observer observer); public void notifyobs

一起学java设计模式--代理模式(结构型模式)

代理模式 应用软件所提供的桌面快捷方式是快速启动应用程序的代理,桌面快捷方式一般使用一张小图片来表示(Picture),通过调用快捷方式的run()方法将调用应用软件(Application)的run()方法.使用代理模式模拟该过程,绘制类图并编程实现. package ProxyPattern; interface Software { void run(); } class Application implements Software { public void run() { Syste

Java设计模式-代理模式之动态代理(附源码分析)

Java设计模式-代理模式之动态代理(附源码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的区别就是:动态代理是在运行时刻动态的创建出代理类及其对象.上篇中的静态代理是在编译的时候就确定了代理类具体类型,如果有多个类需要代理,那么就得创建多个.还有一点,如果Subject中新增了一个方法,那么对应的实现接口的类中也要相应的实习该方法,不符合设计模式原则. 动态代理的做法:在运行时刻,可以动态创建出一个实现了多个接口的代理类.每个代理类的对象都会关联一个表示内部处理

Java设计模式-代理模式之动态代理(附源代码分析)

Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代理是在编译的时候就确定了代理类详细类型.假设有多个类须要代理.那么就得创建多个. 另一点,假设Subject中新增了一个方法,那么相应的实现接口的类中也要相应的实现这些方法. 动态代理的做法:在执行时刻.能够动态创建出一个实现了多个接口的代理类.每一个代理类的对象都会关联一个表示内部处理逻辑的Inv

Java设计模式-代理模式之静态代理

Java设计模式-代理模式之静态代理 概念 为另一个对象提供一个替身或占位符以提供对这个对象的访问,使用代理模式创建代表对象,让代表对象控制某对象的访问,被代理对象可以是远程的对象.创建开销大的对象或需要安全控制的对象 远程代理控制访问远程对象 虚拟代理控制访问创建开销大的资源 保护代理基于权限控制对资源的访问 看如下的类图: 仔细看上面的类图,首先是Subject它为RealSubject和Proxy提供了接口,通过实现同一个接口,Proxy在RealSubject出现的地方取代它,这点和适配

Java设计模式--生成器模式

将一个复杂对象的构建与它的表示分离,使同样的构建过程可以创建不同的表示. Builder Pattern Separate the construction of a complex object from its representation so that the same construction process can create different representations. 类图 模式的结构与使用 生成器模式的结构中包括四个角色. 产品(Product):具体生成器要构造的复

java设计模式 模板方法模式Template Method

设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性.毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因.

Java设计模式——迭代器模式

概述 网上大部分人说迭代模式的时候,总是以某一种可遍历的对象为例进行介绍.这是可行的,这也是迭代模式的基本原型.当我看到<Head Frist设计模式>中迭代模式的时候,感觉要是能从另一个角度来说明,可能更能够体现迭代模式的威力所在. 本文介绍的这种迭代模式,倒是更像是适配器-迭代器模式.希望于你有益~ 版权说明 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:Coding-Naga发表日期: 2016年3月4日链接:http://blog.csdn.net/lemo

Java设计模式——原型模式

概述 原型模式是为了解决一些不必要的对象创建过程.当Java JDK中提供了Cloneable接口之后,原型模式就变得异常的简单了.虽然由于Cloneable的引入使用程序变得更简单了,不过还是有一些需要说明和注意的东西在里面的.文本就详细讲解一下这些注意事项吧. 版权说明 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:Coding-Naga发表日期: 2016年3月3日链接:http://blog.csdn.net/lemon_tree12138/article/d