转载请注明出处!!!http://blog.csdn.net/zhonghuan1992
所有配套代码均在github上:https://github.com/ZHONGHuanGit/DesignPattern
学习桥梁模式之前,最好能够掌握开闭原则和组合复用原则,明白这两个设计原则后,会对该模式的学习有帮助。
首先来看下桥梁模式的定义:将抽象化(Abstraction)和实现(Implementation)解耦,使得两者可以独立地变化。
看到这个定义,可能会百思不得其解,没有关系,我希望看完后续的内容,你就能够解决这个疑惑。下面我们先看一个实例,从实例中体会,桥梁模式。
场景是这样的,我们都知道电视,电灯,电脑都有开关。我们这里只考虑开关,不考虑其它复杂的按钮。好了,电视,电灯和电脑都是家具是吧。好,是家具是吧,那么我们抽象一个家具类,让电视,电灯,和电脑都继承自这个家具类。又因为这些家具类都有开关操作,所以,我们把开关操作抽象到家具类中。
嗯哼,现在设计完家具了,还有一样东西我们没考虑,开关,这个东西该怎么破呢?我们明白他们都有开和关操作,但是,控制器是不一样的,电视的开关是无线控制器开关,也可以是一个按钮那样的开关(这里暂时不考虑电视开的两个步骤,先按遥控按钮开关,再按遥控器。这里假定的是,两个开关都能打开。)。所以现在该怎么办呢?不能用继承吧,如果用继承的话,变成下面这样.仅以电视开关举例。
因为电视开关有两个,这两个开关继承电视,它们可以继承父类的方法,在继承的基础上改进一点。看上去不错的样子,但是这里有什么问题呢?这个问题就是,现在都是智能时代了,其实我们可以用手机来开关我们的电视,电脑,甚至电灯,那么,其实这里只要有一个开关类手机开关就ok了是么,如果按照上面的设计,会多不少类,特别是当家具多的时候。可不能忘了组合复用原则哦!这里能够用组合,为什么不用呢?怎么组合呢?总体设计是这样的,让开关操作抽象出一个抽象开关类,然后具体的开关继承这个抽象开关类,抽象开关具有一个抽象家具类的引用。当要开关操作的时候,就可以调用引用内的开关操作。类图是下面这样的。
设计完毕,这样的设计是不是更佳啊。其实就是为了让开关的方式和家具类解耦,介绍编码量,可以看下图
现在让我们来看一看实现代码。
抽象家具类和电视的的实现:
abstract class Furniture { abstract void turnOn(); abstract void turnOff(); } class TV extends Furniture { void turnOn() { System.out.println("电视打开了"); } void turnOff() { System.out.println("电视关闭了"); } }
抽象开关和智能手机的实现。
abstract class OnOff { // 抽象开关类 Furniture fur; abstract void turnOn(); abstract void turnOff(); void set(Furniture fur) { this.fur= fur; } } // 手机开关 class SmartPhone extends OnOff { void turnOn() { fur.turnOn(); System.out.println("用手机开的"); } void turnOff() { fur.turnOff(); System.out.println("用手机关的"); } }
完整实现可以从我的github上面得到。https://github.com/ZHONGHuanGit/DesignPattern
好了,其实你已经看完一个桥梁模式的实例了。现在让我们来看一下桥梁模式的类图:
上面有四个角色,你可以看到,结合上面的开关例子,我想你对于这四个角色的职责有更好的了解了吧。
抽象画角色Abstraction:抽象化给出的定义,并保存对一个实例化对象的引用。
修正抽象画角色redefinedAbstraction:拓展抽象化角色,改正和修正父类对抽象化的定义。
实现化角色Implementor:给出实现化角色的接口,但不给出具体的定义,必须指出的是,操作的实现接口未必和抽象的接口定义一样,可能会有差别。
具体实现化角色:给出具体的接口实现。
1如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在这两个层次之间建立静态的联系。
2设计要求实现话角色的任何改变不应当影响客户端,或者说实现话改变对客户端是透明的。
3一个构件有多于一个的抽象画角色和实现化角色,系统需要它们之间进行动态的耦合。