一、概念定义
将抽象部分和实现部分分离,使他们都可以独立的变化。(这句话有点抽象啊。。)
在软件系统中,某种类型由于自身逻辑,具有多个维度的变化,如何利用面向对象的技术来使得该类型沿着多方向变化,而又不增加复杂度,这就要引入“Bridge”桥接模式。
二、模式角色
Abstraction:
1.定义抽象接口;
2.拥有一个Impl类型对象引用。
RefinedAbstraction
1.扩展Abstraction的接口定义;
Implementor
1.Implementor是具体实现的接口,Implementor和Abstraction接口并不一定完全一致(注:Proxy和ISubject接口一一对应),实际上这两个接口可以完全不一样,Implementor提供具体操作方法,而Abstraction提供更高层次的调用。
ComcreteImplementor
1.实现Implementor接口,给出具体实现;
三、实例
我们利用汽车在不同道路上行驶的例子来讲解:
汽车:小轿车,公交车
道路:市区街道,高速公路
(我们还可以增加一个维度,驾驶者:男人,女人···)
传统实现(类继承):
上面的实现,导致类的结构过于复杂,继承关系太多,难以维护,扩展性太差,仅仅当汽车类型和道路变化 ,就会使类的结构更大。
利用桥接模式的实现:
而利用桥接模式,把两个角色之间的关系由继承改为了耦合的关系;从而使两者可以自由的变化。
抽象类:【代码清单---1】
1 package com.huawei.bridgeDesign01.Abstract; 2 /** 3 * 抽象汽车 4 * @author Administrator 5 * 6 */ 7 public abstract class AbstractCar 8 { 9 public abstract void run(); 10 } 11 ======================== 12 package com.huawei.bridgeDesign01.Abstract; 13 14 /** 15 * 抽象道路 16 * @author Administrator 17 * 18 */ 19 public abstract class AbstractRoad 20 { 21 public AbstractCar aCar; 22 23 public abstract void run(); 24 25 public AbstractCar getaCar() { 26 return aCar; 27 } 28 29 public void setaCar(AbstractCar aCar) { 30 this.aCar = aCar; 31 } 32 } 33 =============================== 34 package com.huawei.bridgeDesign01.Abstract; 35 36 /** 37 * 抽象驾驶者 38 * @author Administrator 39 * 40 */ 41 public abstract class People 42 { 43 public AbstractRoad road; 44 public abstract void run(); 45 }
具体实现类【代码清单---2】
汽车类:
1 package com.huawei.bridgeDesign01.Impl; 2 3 /** 4 * 公交车实现类 5 */ 6 import org.apache.log4j.Logger; 7 8 import com.huawei.bridgeDesign01.Abstract.AbstractCar; 9 10 public class Bus extends AbstractCar 11 { 12 public static final Logger LOGGER = Logger.getLogger(Bus.class); 13 14 @Override 15 public void run() 16 { 17 LOGGER.info("公交车"); 18 } 19 } 20 =============================== 21 package com.huawei.bridgeDesign01.Impl; 22 /** 23 * 小汽车实现类 24 */ 25 import org.apache.log4j.Logger; 26 27 import com.huawei.bridgeDesign01.Abstract.AbstractCar; 28 29 public class Car extends AbstractCar 30 { 31 public static final Logger LOGGER = Logger.getLogger(Car.class); 32 33 @Override 34 public void run() 35 { 36 LOGGER.info("小汽车"); 37 } 38 }
道路类【代码清单---3】
1 package com.huawei.bridgeDesign01.Impl; 2 /** 3 * 高速公路具体类 4 */ 5 import org.apache.log4j.Logger; 6 7 import com.huawei.bridgeDesign01.Abstract.AbstractRoad; 8 9 public class SpeedWay extends AbstractRoad 10 { 11 public static final Logger LOGGER = Logger.getLogger(SpeedWay.class); 12 13 @Override 14 public void run() 15 { 16 aCar.run(); 17 LOGGER.info("在高速公路上行驶"); 18 } 19 } 20 ===================================== 21 package com.huawei.bridgeDesign01.Impl; 22 /** 23 * 市区街道具体类 24 */ 25 import org.apache.log4j.Logger; 26 27 import com.huawei.bridgeDesign01.Abstract.AbstractRoad; 28 29 public class Street extends AbstractRoad 30 { 31 public static final Logger LOGGER = Logger.getLogger(Street.class); 32 @Override 33 public void run() 34 { 35 aCar.run(); 36 LOGGER.info("在市区街道行驶"); 37 } 38 }
驾驶者类【代码清单---4】
1 package com.huawei.bridgeDesign01.Impl; 2 /** 3 * 男人具体类 4 */ 5 import org.apache.log4j.Logger; 6 7 import com.huawei.bridgeDesign01.Abstract.People; 8 9 public class Man extends People 10 { 11 public static final Logger LOGGER = Logger.getLogger(People.class); 12 @Override 13 public void run() 14 { 15 LOGGER.info("男人开着"); 16 road.run(); 17 } 18 } 19 ================================= 20 package com.huawei.bridgeDesign01.Impl; 21 /** 22 * 女人具体类 23 */ 24 import org.apache.log4j.Logger; 25 26 import com.huawei.bridgeDesign01.Abstract.People; 27 28 public class Women extends People 29 { 30 public static final Logger LOGGER = Logger.getLogger(Women.class); 31 @Override 32 public void run() 33 { 34 LOGGER.info("女人开着"); 35 road.run(); 36 } 37 }
测试类【代码清单---5】
1 package com.huawei.bridgeDesign01; 2 3 import org.apache.log4j.Logger; 4 5 import com.huawei.bridgeDesign01.Abstract.AbstractRoad; 6 import com.huawei.bridgeDesign01.Abstract.People; 7 import com.huawei.bridgeDesign01.Impl.Bus; 8 import com.huawei.bridgeDesign01.Impl.Car; 9 import com.huawei.bridgeDesign01.Impl.Man; 10 import com.huawei.bridgeDesign01.Impl.SpeedWay; 11 import com.huawei.bridgeDesign01.Impl.Street; 12 import com.huawei.bridgeDesign01.Impl.Women; 13 14 public class Main02 15 { 16 public static final Logger LOGGER = Logger.getLogger(Main02.class); 17 18 public static void main(String[] args) 19 { 20 LOGGER.info("Enter Main02.class..."); 21 AbstractRoad speedWay = new SpeedWay(); 22 speedWay.aCar = new Car(); 23 People man = new Man(); 24 man.road = speedWay; 25 man.run(); 26 27 AbstractRoad street = new Street(); 28 street.aCar = new Bus(); 29 People women = new Women(); 30 women.road = street; 31 women.run(); 32 LOGGER.info("Exit Main02.class...."); 33 } 34 }
四、效果及实现要点
1.Bridge模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着自己的方向来变化;
2.所谓抽象和实现沿着各自维度的变化,即“子类化”它们,得到各个子类之后,便可以任意它们,从而获得不同路上的不同汽车。
3.Bridge模式有时候类似于多继承方案,但是多继承方案往往违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。
4.Bridge模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向的变化维度并不剧烈——换言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。
五、应用及拓展
适用性:
1.如果一个软件系统需要在抽象角色和具体实现之间增加更多的灵活性;
2.设计要求具体化角色的任何改变不影响客户端,或者说具体化角色的改变对客户端来说是完全透明的;
3.一个系统有多个抽象画角色和实现化角色,系统需要他们之间进行动态耦合;
与装饰者模式的区别:
这两个类都是为了减少子类的数目,避免出现复杂的类继承关系。
装饰者模式:装饰者模式是把子类中比基类中多出来的部分放到单独的类里面,以适应新功能增加的需要。当我们
把描述新功能的类封装到基类的对象里面时,就得到了所需要的子类对象,这些描述新功能的类通过组合可以实现
很多的功能组合。
桥接模式:它把原来的基类的实现化细节抽象出来,再构造一个实现化的结构中,然后把原来的基类改造成
一个抽象化的等级结构,这样就可以实现在多个维度上的独立自由变化。