Bridge模式(桥接模式),要解决的问题是一个抽象类的派生类使用多种实现部分,但又不能引起类数量的爆炸。
它的主要意图是将一组实现部分从另一组使用它们的对象中分离出来,使它们都可以独立的变化。这句话是不是很
难理解?用Alan Shalloway的话讲,分离是指“让各部分的行为各自独立,或至少显式指出关联”,抽象部分是指
“不同事物在概念层次上的联系”,实现部分就是“抽象类的对象和用来实现抽象类的派生类的对象”,但是到底怎
样将抽象部分与实现它的特定方式分离呢?
Alan Shalloway在《Design Patterns Explained》一书中提到,学习Bridge模式应遵循两个基本原则:
1.发现并封装变化点;
2.优先使用对象组合而不是类继承;
在独立的类中包含变化点,从而使未来的变化不会影响现在的代码,为此,将所有的变化点都包含在自己的抽象类中,
然后观察抽象类彼此之间如何发生关联。
上面这些听起来有些费解。
下面我用一些例子说明一下我对这两条原则的理解。在一些网络游戏中,经常会有各种门派之分,各门派又有不同的
技能和经验之别,举例来说,现有一游戏,只有少林和武当两派,少林的血上限和外公防御可以说是最高的,配上吸引
怪物的攻击技能,可以堪称钢铁肉盾,武当的血虽少,但封系招数极多,使敌人无法靠近,又能以蓝减少血的流失,也
不可忽视。假设两派均有攻击(attack)和防御(defend)技能,虽然强度不同。那么这个游戏的变化点有哪些呢?
一是派别极有可能会增加,再就是各派的技能会有改变。
再举一个例子,就是Alan这本书中的例子,假设你接到一个任务:编写一个画矩形的程序,它可以使用两个画图程序中
的任何一个,当实例化一个矩形时,你将知道是应该使用画图程序1还是画图程序2?在这个案例中,变化点是“不同类型
的形状”(因为以后可能扩展圆形,三角形等),和“不同类型的画图程序”(因为以后可能有更多的画图程序可供使用)。
那么这里共同的概念是“形状”和“画图程序”,可用两个抽象类表示,图略。
结合作者的讲解,下面详细化这个例子。
Shape类就用来封装形状的概念,Drawing类则用来封装画图的概念。
根据描述,很容易会有下面的设计:
如何让们彼此关联呢?可以让Shape类使用Drawing类。
这样,左边就是包含了抽象部分的变化点,右边包含了实现抽象部分的变化点,二者的分离,避免了
类的爆炸。
此外还有一条应遵循的策略:只在一个地方实现一条规则。虽然Rectangle对象的draw方法可以直接
调用Shape类拥有的Drawing对象的drawLine方法,但还是按照该策略,让shape类的drawLine方
法调用其拥有的Drawing对象的drawingLine方法,drawCircle方法采取同样的策略。
这样可以消除重复工作。