一、DIP 依赖反转原则
1、在了解何谓桥接模式之前,我们先来看一下经典的面向对象设计原则之一:DIP原则。所谓DIP原则,即Dependency Inversion Principle,用中文解释就是“依赖反转原则”(下面将要介绍的桥接模式就是基于DIP原则设计的)。
2、在传统的面向过程的程序设计中,模块之间的关系式:
(1)高层次模块 依赖 低层次模块 (2)抽象模块 依赖 具体模块
3、这种依赖关系的弊端是: 底层次的、具体的模块,通常是一些逻辑处理或算法实现,这部分的代码是易变的,不稳定。这样产生的后果就是:让一个系统中稳定的部分依赖那些不稳定的部分,那么不稳定部分的改变将影响到整个系统,从而增加整个系统扩展的复杂度;
4、PS. 用一个通俗的例子解释上面的话:有一家产品公司,老板(高层次、抽象)做的工作应该是什么?是要告诉工人生产什么样的产品。而产品最终具体的生产制作是由工人来完成的。在面向过程的程序设计中讲的问题就是:不管你老板的本意是要做多么多么好的产品,但最终产品出货的样子还是由工人来决定。这就是 高层次模块依赖低层次模块。
5、因此,”依赖反转原则“的目的就是要解决上面的问题:我们设计的程序要让具体依赖抽象,既要面向接口编程,不要面向实现编程。
6、这里还要继续不嫌啰嗦的解释下”面向接口编程“:所谓面向接口编程,就是使用java中的”接口“或”抽象类“进行变量的声明,参数的声明,方法的返回类型声明
二、面向接口编程的程序结构图:
1、Implementor(接口):一般而言,Implementor接口仅提供基本操作,而Abstraction定义的接口可能会做更多更复杂的操作。Implementor接口对这些基本操作进行了声明,而具体实现交给其子类。通过关联关系(这种关联关系就是在abstraction抽象类中声明一个该implementor类型的变量,并声明或定义一些方法来维护这个变量,在下面的F1赛车例子中就是那个tire),在Abstraction中不仅拥有自己的方法,还可以调用到Implementor中定义的方法,使用关联关系来替代继承关系
2、Abstraction(抽象类):其中定义了一个Implementor(实现类接口)类型的对象并可以维护该对象(这个对象只是一个引用,它将最终指向implementor的具体实现类的一个实例对象),它与Implementor之间具有关联关系,它既可以包含抽象业务方法,也可以包含具体业务方法。
3、ConcreteImplementor(接口的具体实现类):具体实现Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同实现,在程序运行时,ConcreteImplementor对象将替换其父类对象(就是传说中的父类引用指向子类对象),提供给抽象类具体的业务操作方法。
4、RefinedAbstraction(抽象类的具体实现类):扩充由Abstraction定义的接口,通常情况下它不再是抽象类而是具体类,它实现了在Abstraction中声明的抽象业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。
三、桥接模式的一个示例:
看过F1的朋友都知道,有时候会出现下雨情况,这时候车队就会给赛车换轮胎。已这个作为示例,演示一下桥接。
1、接口 Implementor
public interface ITire { void function(); }
public abstract class F1 { public ITire tire; public void setTire(ITire tire){ this.tire = tire; ForNewTires(); } public abstract void ForNewTires(); }
(1)干胎
public class DryTyres implements ITire { @Override public void function() { // TODO Auto-generated method stub System.out.println("天气晴朗,使用干胎"); } }
public class IntermediateTyre implements ITire{ @Override public void function() { // TODO Auto-generated method stub System.out.println("刚刚开始下雨,换中性胎"); } }
(3)雨胎
public class RainTires implements ITire{ @Override public void function() { // TODO Auto-generated method stub System.out.println("雨胎,适合积水较多时使用"); } }4、实现抽象类的具体实类
(1)法拉利
/** *法拉利 */ public class F10 extends F1 { @Override public void ForNewTires() { // TODO Auto-generated method stub System.out.println("这是法拉利赛车"); tire.function(); } }(2)雷诺
/** *雷诺 R25 */ public class RenaultR25 extends F1 { @Override public void ForNewTires() { // TODO Auto-generated method stub System.out.println("这是雷诺赛车"); tire.function(); } }
public static void main(String[] args) { // TODO Auto-generated method stub //准备好轮胎和赛车 ITire tire = new DryTyres(); ITire tire2 = new IntermediateTyre(); ITire tire3 = new RainTires(); //法拉利的F10 F10 f10 = new F10(); //雷诺的R25 RenaultR25 r25 = new RenaultR25(); System.out.println("--比赛开始天气晴朗--"); f10.setTire(tire); r25.setTire(tire); System.out.println("--比赛中开始下雨--"); f10.setTire(tire2); r25.setTire(tire2); System.out.println("--比赛中雨越下越大,出现积水--"); f10.setTire(tire3); r25.setTire(tire3); }