Bridge定义:将抽象和行为划分开来,各自独立,但能动态的结合。

为什么使用桥模式

通常,当一个抽象类或接口有多个具体实现(concrete subclass),这些concrete之间关系可能有以下两种:

  • 这多个具体实现之间恰好是并列的,如前面举例,打桩,有两个concrete class:方形桩和圆形桩;这两个形状上的桩是并列的,没有概念上的重复,那么我们只要使用继承就可以了。
  • 实际应用上,常常有可能在这多个concrete class之间有概念上重叠。那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个接口,分别放置抽象和行为。

例如,一杯咖啡为例,有中杯和大杯之分,同时还有加奶 不加奶之分。如果用单纯的继承,这四个具体实现(中杯 大杯 加奶 不加奶)之间有概念重叠,因为有中杯加奶,也有中杯不加奶,如果再在中杯这一层再实现两个继承,很显然混乱,扩展性极差。那我们使用Bridge模式来实现它。

如何实现桥模式

以上面提到的咖啡 为例。我们原来打算只设计一个接口(抽象类),使用Bridge模式后,我们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口。

先看看抽象部分的接口代码:

public abstract class Coffee{
 CoffeeImp coffeeImp;
 public void setCoffeeImp() {
  this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp();
 }
 public CoffeeImp getCoffeeImp() {return this.CoffeeImp;}
 public abstract void pourCoffee();
}

其中CoffeeImp 是加不加奶的行为接口,看其代码如下:

public abstract class CoffeeImp{
 public abstract void pourCoffeeImp();
}

现在我们有了两个抽象类,下面我们分别对其进行继承,实现concrete class:

//中杯
public class MediumCoffee extends Coffee{
 public MediumCoffee() {setCoffeeImp();}
 public void pourCoffee(){
  CoffeeImp coffeeImp = this.getCoffeeImp();
  //我们以重复次数来说明是冲中杯还是大杯 ,重复2次是中杯
  for (int i = 0; i < 2; i++){
   coffeeImp.pourCoffeeImp();
  }
 }
}
//大杯

public class SuperSizeCoffee extends Coffee{
 public SuperSizeCoffee() {setCoffeeImp();}
 public void pourCoffee(){
  CoffeeImp coffeeImp = this.getCoffeeImp();
  //我们以重复次数来说明是冲中杯还是大杯 ,重复5次是大杯
  for (int i = 0; i < 5; i++){
   coffeeImp.pourCoffeeImp();
  }
 }
}

上面分别是中杯和大杯的具体实现.下面再对行为CoffeeImp进行继承:

//加奶
public class MilkCoffeeImp extends CoffeeImp{
 MilkCoffeeImp() {}
 public void pourCoffeeImp(){
  System.out.println("加了美味的牛奶");
 }
} //不加奶
public class FragrantCoffeeImp extends CoffeeImp{
 FragrantCoffeeImp() {}
 public void pourCoffeeImp(){
  System.out.println("什么也没加,清香");
 }
}

Bridge模式的基本框架我们已经搭好了,别忘记定义中还有一句:动态结合,我们现在可以喝到至少四种咖啡:

  1. 中杯加奶
  2. 中杯不加奶
  3. 大杯加奶
  4. 大杯不加奶

看看是如何动态结合的,在使用之前,我们做个准备工作,设计一个单态类(Singleton)用来hold当前的CoffeeImp:

public class CoffeeImpSingleton{
 private static CoffeeImp coffeeImp;
 public CoffeeImpSingleton(CoffeeImp coffeeImpIn)
 {this.coffeeImp = coffeeImpIn;}
 public static CoffeeImp getTheCoffeeImp(){
  return coffeeImp;
 }
}
看看中杯加奶 和大杯加奶 是怎么出来的: //拿出牛奶
CoffeeImpSingleton coffeeImpSingleton = new CoffeeImpSingleton(new MilkCoffeeImp()); //中杯加奶
MediumCoffee mediumCoffee = new MediumCoffee();
mediumCoffee.pourCoffee(); //大杯加奶
SuperSizeCoffee superSizeCoffee = new SuperSizeCoffee();
superSizeCoffee.pourCoffee();

注意:Bridge模式的执行类如CoffeeImp和Coffee是一对一的关系,正确创建CoffeeImp是该模式的关键。

Bridge模式在EJB中的应用

EJB中有一个Data Access Object (DAO)模式,这是将商业逻辑和具体数据资源分开的,因为不同的数据库有不同的数据库操作。将操作不同数据库的行为独立抽象成一个行为接口DAO,如下:

    • Business Object (类似Coffee)
      实现一些抽象的商业操作:如寻找一个用户下所有的订单。涉及数据库操作都使用DAOImplementor。
    • Data Access Object (类似CoffeeImp)
      一些抽象的对数据库资源操作。
    • DAOImplementor 如OrderDAOCS, OrderDAOOracle, OrderDAOSybase(类似MilkCoffeeImp FragrantCoffeeImp)
      具体的数据库操作,如"INSERT INTO "等语句,OrderDAOOracle是Oracle OrderDAOSybase是Sybase数据库。
    • 数据库 (Cloudscape, Oracle, or Sybase database via JDBC API)

系列文章:

Java设计模式(1)工厂模式(Factory模式)

Java设计模式(2)单态模式(Singleton模式)

Java设计模式(3)建造者模式(Builder模式)

Java设计模式(4)原型模式(Prototype模式)

Java设计模式(5)共享模式/享元模式(Flyweight模式)

Java设计模式(6)桥模式(Bridge模式)

Java设计模式(7)装饰模式(Decorator模式)

Java设计模式(8)组合模式(Composite模式)

Java设计模式(9)适配器模式(Adapter模式)

Java设计模式(10)代理模式(Proxy模式)

Java设计模式(11)外观模式(Facade模式)

Java设计模式(12)迭代模式(Iterator模式)

Java设计模式(13)模板模式(Template模式)

Java设计模式(14)责任链模式(Chain of Responsibility模式)

Java设计模式(15)备忘录模式(Memento模式)

Java设计模式(16)中介模式(Mediator模式)

Java设计模式(17)解释器模式(Interpreter模式)

Java设计模式(18)策略模式(Strategy模式)

Java设计模式(19)状态模式(State模式)

Java设计模式(20)观察者模式(Observer模式)

Java设计模式(21)访问模式(Visitor者模式)

Java设计模式(22)命令模式(Command模式)

Java设计模式(6)桥模式(Bridge模式)的更多相关文章

  1. Java设计模式(22)命令模式(Command模式)

    Command模式是最让我疑惑的一个模式,我在阅读了很多代码后,才感觉隐约掌握其大概原理,我认为理解设计模式最主要是掌握起原理构造,这样才对自己实际编程有指导作用.Command模式实际上不是个很具体 ...

  2. Java设计模式(21)访问模式(Visitor者模式)

    Visitor定义:作用于某个对象群中各个对象的操作.它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作. 在Java中,Visitor模式实际上是分离了collection结构中的元 ...

  3. Java设计模式(19)状态模式(State模式)

    State的定义:不同的状态,不同的行为:或者说,每个状态有着相应的行为. 何时使用状态模式 State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If else ...

  4. Java设计模式(18)策略模式(Strategy模式)

    Strategy是属于设计模式中 对象行为型模式,主要是定义一系列的算法,把这些算法一个个封装成单独的类. Stratrgy应用比较广泛,比如,公司经营业务变化图,可能有两种实现方式,一个是线条曲线, ...

  5. Java设计模式(17)解释器模式(Interpreter模式)

    Interpreter定义:定义语言的文法,并且建立一个解释器来解释该语言中的句子. Interpreter似乎使用面不是很广,它描述了一个语言解释器是如何构成的,在实际应用中,我们可能很少去构造一个 ...

  6. Java设计模式(16)中介模式(Mediator模式)

    Mediator定义:用一个中介对象来封装一系列关于对象交互行为. 为何使用Mediator模式/中介模式 各个对象之间的交互操作非常多,每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉 ...

  7. Java设计模式(15)备忘录模式(Memento模式)

    Memento定义:memento是一个保存另外一个对象内部状态拷贝的对象,这样以后就可以将该对象恢复到原先保存的状态. Memento模式相对也比较好理解,我们看下列代码: public class ...

  8. Java设计模式(13)模板模式(Template模式)

    Template模式定义:定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中. 其实Java的抽象类本来就是Template模式,因此使用很普遍.而且很容易理解和使用,我们直接以示例开始: pu ...

  9. Java设计模式(12)迭代模式(Iterator模式)

    上了这么多年学,我发现一个问题,好象老师都很喜欢点名,甚至点名都成了某些老师的嗜好,一日不点名,就饭吃不香,觉睡不好似的,我就觉得很奇怪,你的课要是讲的好,同学又怎么会不来听课呢,殊不知:“误人子弟, ...

  10. Java设计模式(11)外观模式(Facade模式)

    外观模式(Facade)的定义:为子系统中的一组接口提供一个一致的界面. Facade一个典型应用就是数据库JDBC的应用,如下例对数据库的操作: public class DBCompare { C ...

随机推荐

  1. IOS 实现录音PCM转MP3格式(边录音边转码)

    最近做的一个项目,项目中有个录音功能,采用的录音方法是IOS下的AVAudioRecorder.录音效果不错,但是录制的原生.pcm文件太大,每分钟大约10M左右. 找了下相关的音频压缩方法,用spe ...

  2. 【Unity】6.2 在VS2015中调试 C# 脚本

    分类:Unity.C#.VS2015 创建日期:2016-04-16 一.简介 这一节先利用GUI显示一个简单的界面(以后还会专门介绍GUI),并解释如何在VS2015中调试C#脚本. 本节例子的运行 ...

  3. cannot send list of active checks to [ZabbixServerIp]: host [Zabbix server] not found

    解决办法 因为web端上被监控端的主机名和zabbix_agentd.conf中的Hostname名字不一样,改为一样的即可 注意发现问题一定要看日志: tail -f /var/log/zabbix ...

  4. G1 Garbage Collector and Shenandoah

    http://www.diva-portal.se/smash/get/diva2:754515/FULLTEXT01.pdf https://is.muni.cz/th/ifz8g/GarbageC ...

  5. bat批处理延迟运行脚本

    @echo off:aaapause 这里是你需要运行的程序for /l %%i in (0,1,10000) do echo %%i>nulgoto aaa 当然bat延迟运行还有其他的一些方 ...

  6. SVN四部曲之SVN设置详解深入

    想知道不同的设置是干什么用的,你只需将鼠标指针在编辑框/选项框上停留一秒钟...一个帮助提示气泡就会弹出来. 常规设置 图 4.68. 设置对话框,常规设置页面 这个对话框允许你指定自己喜欢的语言,同 ...

  7. ubuntu下安装vmTools, 和共享文件

    如果没有需要下载一个vmTools,我是下载的 然后加载到光驱,然后在ubuntu下面可以找到光驱 解压里面的文件, 我解压到 Documents下面 然后ctrl + alt + t进入控制台 cd ...

  8. 【ARM】ARM程序规范

    1.函数名单词之间用_隔开,每一个字母大写      Uart_Printf()    //这个由三星的TEST风格延续下来,因此没有参数时,必须加void,否则ADS会编译报警    void Te ...

  9. linux centOS6 nexus 开启自动启动

    sudo ln -s /opt/nexus-2.6.4/nexus-2.6.4-02/bin/nexus /etc/init.d/nexus 使用  service nexus status/star ...

  10. 九章面试题:Find first K frequency numbers 解题报告

    Find first K frequency numbers /* * Input: int[] A = {1, 1, 2, 3, 4, 5, 2}; k = 3 * return the highe ...