一、制作计算器的外壳
如果要制作计算器的外壳,外壳类主要有两个属性,颜色和材质,不同颜色和材质的组合就是不同的外壳对象。例如颜色有三种变化:红、绿、黄,材质也有三种选择:塑料、金属、陶瓷,就可以组合出九种不同的计算器,如果每种计算器都需要实现其特定的功能,那么就需要九个子类来继承外壳类。
实际上,如果把颜色单独抽象出来作为一个对象,那么颜色的变化就不在外壳类的考虑范围内,外壳类只需扩展三种材质的子类即可,而让颜色类自己去扩展自己的子类。然后在客户端中自由组合外壳种类和颜色种类。
像这种要实现的对象、系统可能有多角度的分类,每一种分类都可能有很多种变化的情况,只用继承会增加大量的子类。就可使用桥接模式,把这种多角度分离出来让他们独立变化,减少他们之间的耦合。
二、桥接模式
桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。
实现是指抽象类和它的派生类用来实现自己的对象。由于实现的方式有多种,桥接模式的核心意图就是把这些实现独立出来,让他们各自地变化。这就使得每种实现的变化不会影响其他实现,从而达到应对变化的目的。
在使用桥接模式时,我们首先应该识别出一个类所具有的两个独立变化的维度,将它们设计为两个独立的继承等级结构,为两个维度都提供抽象层,并建立抽象耦合。
桥接是一个接口,它与一方应该是绑定的,也就是解耦的双方中的一方必然是继承这个接口的,这一方就是实现方,而另一方正是要与这一方解耦的抽象方,如果不采用桥接模式,一般我们的处理方式是直接使用继承来实现,这样双方之间处于强链接,类之间关联性极强,如要进行扩展,必然导致类结构急剧膨胀。采用桥接模式,正是为了避免这一情况的发生,将一方与桥绑定,即实现桥接口,另一方在抽象类中调用桥接口(指向的实现类),这样桥方可以通过实现桥接口进行单方面扩展,而另一方可以继承抽象类而单方面扩展,而之间的调用就从桥接口来作为突破口,不会受到双方扩展的任何影响。
三、桥接模式的角色
使用桥接模式制造不同的计算器外壳的类图:
Abstraction(抽象类):用于定义抽象类的接口,它一般是抽象类而不是接口,其中定义了一个Implementor(实现类接口)类型的对象并可以维护该对象,它与Implementor之间具有关联关系,它既可以包含抽象业务方法,也可以包含具体业务方法。
RefinedAbstraction(扩充抽象类):扩充由Abstraction定义的接口,通常情况下它不再是抽象类而是具体类,它实现了在Abstraction中声明的抽象业务方法,在RefinedAbstraction中可以
调用在Implementor中定义的业务方法。
Implementor(实现类接口):定义实现类的接口,这个接口不一定要与Abstraction的接口完全一致,事实上这两个接口可以完全不同,一般而言,Implementor接口仅提供基本操作,而Abstraction定义的接口可能会做更多更复杂的操作。Implementor接口对这些基本操作进行了声明,而具体实现交给其子类。通过关联关系,在Abstraction中不仅拥有自己的方法,还可以调用到Implementor中定义的方法,使用关联关系来替代继承关系。
ConcreteImplementor(具体实现类):具体实现Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同实现,在程序运行时,ConcreteImplementor对象将替换其父类对象,提供给抽象类具体的业务操作方法。
四、使用桥接模式制造计算器外壳
4.1 抽象外壳类
public abstract class Shell {
protected Color color;
public void