Java设计模式——桥接模式

来源:互联网 发布:sql distinct 所有字段 编辑:程序博客网 时间:2024/06/13 06:55

相关文章:
Java设计模式——观察者模式
Java模式——适配器模式

桥接模式的官方解释是:
将抽象部分与实现部分分离,使它们都可以独立的变化

意思就是将抽象的依赖关系,转到实现对象上,减少类与类之间的静态耦合,当开发中有某个类涉及到多维度的变化时,使用继承会使代码变得非常臃肿,这时就需要考虑,怎么才能解除这些复杂且多余的继承关系,将其可能的变化转移到实现时的对象身上呢?“桥接模式”就是一种解决之道。

来举个例子,我想要去旅游,那该去哪呢?又该怎么过去呢?旅游胜地有很多,且可选择的途径也很有多,火车、汽车、飞机….各种各样的交通工具,这时 在“去旅游”这件事上就产生了可能的维度变化,因为没人知道我会去什么地方旅游,通过什么途径过去,也许是去内蒙古看草原,也许是去北京看天安门,去的时候可能坐飞机、也许没钱买机票就去坐火车、本宝宝疯起来骑自行车去也是有可能的。那么系统该怎么设计才能保证提供所有的搭配可能呢?
如果使用静态的继承关系来实现的话的话可能是这样

public class Train{    public void run(){        System.out.println("坐火车");    }}public class Plane{    public void run(){        System.out.println("坐飞机");    }}public class BeiJingByTrain extends Train{    public void start(){        run();        System.out.println("去北京旅游");    }public class BeiJingByPlane extends Plane{    public void start(){        run();        System.out.println("去北京旅游");    }public class ShangHaiByTrain extends Train{    public void start(){        run();        System.out.println("去上海旅游");    }}public class ShangHaiByPlane extends Plane{    public void start(){        run();        System.out.println("去上海旅游");    }public class Test{    public static void main(Stirng args[]){        new BeiJingByTrain().start();        new ShangHaiByPlane().start();    }}

由上边的代码可以看到,只是实现了去北京和上海的方式,只提供了火车、和飞机两种交通工具,就已经产生了不少继承关系,最终实现的类有2+2*2=6个(2个交通工具+2个城市实现每个交通工具)
如果要实现10个或者是100个城市和所有的交通工具任意组合,那会出现非常多的继承关系,计算一下,假设10种交通工具100个城市的话,就会有10+100*10=1010个类
这样对我们的工程是不利的,那怎么解决呢。前面说了我们需要把可变的因素转移到实现时的对象上,而不是去大量的使用继承。现在来分析分析旅游这件事,对于“旅游”来说:有一个抽象的概念,就是“我会乘某种交通工具去某个地方”,这是“必然”;而这个抽象实现的时候会变成“我会乘 火车/飞机/汽车…. 去 北京/上海/南京….”中任何一种可能
那么现在就来实现“把可变因素放到实现时的对象上”

//首先,在考虑可变因素前,先将“必然”的抽象关系确定,即“会乘某种工具,去某个地方”//“某种交通工具”interface IVehicle{    public void run();}//“某个地方”abstract class ICity{    //到达这个地方使用的“某种交通工具”    IVehicle mVehicle;    public ICity(IVehicle vehicle){        this.mVehicle=vehicle;    }    //出发    public abstract void start();}//可实现具体类public class Train implement IVehicle{    public void run(){        System.out.println("坐火车");    }}public class Plane implement IVehicle{    public void run(){        System.out.println("坐飞机");    }}public class BeiJing extends ICity{    public BeiJing(IVehicle vechicle){        super(vechicle);    }    public void start(){        super.mVehicle.run();        System.out.println("去北京旅游");    }}public class ShangHai extends ICity{    public ShangHai(IVehicle vechicle){        super(vechicle);    }    public void start(){        super.mVehicle.run();        System.out.println("去上海旅游");    }public class Test{    public static void main(String args[]){        //这里即是实现时所使用的对象,将变化在这里实现,在这里选择并创建交通工具        IVehicle vehicle=new Train();        //然后选择一个城市,使用这个交通工具,即可达成任意的组合;在ICity的实体类和IVehicle实体类之间,不再有任何继承关系        ICity city=new Beijing(vehicle);        city.start();    }}

仅仅是两个交通工具和城市好像看起来产生的类没有减少,依然是6个类,但计算方式却不一样了,1+1+2+2=6(交通抽象类+城市抽象类+交通实体类+城市实体类)
如果还是假设有10种交通工具,100个城市,那么就有1+1+10+100=112个类,比之前计算出的1010少了近九成,这时桥接模式的好处就体现出来了,使用两个抽象类,将“城市”和“交通工具”抽象的桥接在了一起

上面用代码的方式理解了桥接模式,现在再举一个例子,用两张简单粗暴的图看一下:
现在有一张菜单,店铺有优惠,凑齐一菜一汤可以召唤神龙,先看看这张菜单的两种形式:
这里写图片描述

这里写图片描述

可以看到两张菜单的不同点在于
第一张:将套餐组合排列出来供顾客选择
第二张:将现有的菜和汤分别列出,让顾客主动去搭配

现在结合上面的代码例子分析一下菜单:

菜单上的选项 : 代码中的实体类
”主菜“:菜品的抽象
”汤“:汤的抽象
“+”:可以看作是”extends”
而顾客在下划线中填写选项这一过程,就是代码中使用类的过程(上面代码的main方法)

所以
第一张菜单写了16个实体类(如果在代码中实现,继承的前提还要先写出父类,即4个汤,那就是20个类),第二张有八个实体类
第一张没有抽象类,第二张有两个抽象类

如果要点(红烧肉+ 西红柿蛋汤)

//那么在一张菜单中填写  A 代表的就是:main(){    (红烧肉 extend 西红柿蛋汤) food = new (红烧肉 extend 西红柿蛋汤)();}//而在第二张菜单中分别填写 A 和 a  代表的就是:main(){    汤 soup = new 西红柿蛋汤();    菜 food = new 红烧肉(soup);}

两种方式实现了同一个功能
第一种将所有可能的选择都放在的静态的继承关系上

而第二种将这一不确定因素放在了实现的地方,使用两个抽象类,将“菜”和“汤”两个维度的东西桥接在了一起,仅仅是使用的时候多了一个可变步骤,就减少了大量类的创建

如上所述,便是“桥接模式”,它成功解除了两个维度之间的静态耦合,通过让City持有一个Vehicle对象的方式,将“可变性”转移到了实现时的对象身上,依赖对象实现了可变性。

1 0