分类:
2008-10-13 16:56:52
Strategy在GoF等人的书中,被阐述为针对同一问题的若干种算法的独立封装。对于Bridge,则被表述为将若干对象方法的实现与对象本身分别封装。
Strategy、Bridge看似风马牛不相及的两种Pattern,却正是由于二者均表现为将方法的实现与方法所属的对象分别进行封装,而让我迷惑了许久。
(一)Strategy
现在,我理解的Strategy更象是C/C++语言中的头文件.H与库文件.LIB的关系。比如.H中声明的同一个方法malloc(),可能会因为编译模式的选择(Tiny/Small/Large),使malloc()的编译依赖指向不同的.LIB中malloc()的实现,比如malloc_tiny()、malloc_small()、malloc_large()。
Strategy或者也可以用一个参加宴会的人如何使用餐具作比:参加中式宴会时,使用筷子;参加西式宴会时,使用刀叉。
在这两个例子里,“malloc()”与“使用餐具”是Strategy中要被抽象的那个方法;“编译模式”与“宴会类型(中/西)”是Strategy中的Configuration对象;malloc_tiny()、“使用筷子”、“使用刀叉”则分别是派生的ConcreteStrategy对象。最后由“参加宴会的人”根据自己参加的是中式亦或西式的宴会(获取Configuration对象),决定是“使用筷子”还是“使用刀叉”(创建对应的ConcreteStrategy对象)。
在Strategy Pattern中,一个Strategy对象总是与一个方法Method()对应的,若干个派生的Strategy对象间是互斥的,所有的ConcreteStrategy对象都只能属于同一个Method()。换句话说,任一时刻Method()只能是指向其中的一个Strategy对象。
(二)Template
Template也是将方法与其实现相剥离的一种Pattern,它只是在Strategy的基础上作出了更多的限制——预定义了方法的具体实现步骤。可以理解为,Strategy只是将Method()与Method_Imp()进行了剥离,而Template是将Method()表示为Method_Imp()后,继续将Method_Imp()割裂为Method_Imp_Step1()、Method_Imp_Step2()、Method_Imp_Step3()等。
在Martin的Head First一书里,用泡咖啡与泡柠檬茶对Template Pattern做了最形象的比喻。泡咖啡或是泡茶,都要经过几个步骤:烧水->放入咖啡/茶叶->把泡好的咖啡/茶盛入杯子->加奶/柠檬。于是在Template中,他定义了BoilWater()->Brew()->PourInCup()->AddCondiments()这么一个顺序,构成一个完成的泡制饮品的方法,区别的只是泡茶时Brew()放的是茶,AddCondiments()时放的是柠檬。
我时常在想,为什么国内的专家们就不能举出这么简单的例子,让我们一下就明白Pattern是什么呢?他们要不把简单的问题复杂化,要不就照抄别人的例子。
(三)Bridge
曾经以为自己对Bridge的理解是最为深刻的,因为这是《Design Pattern Explained》奉上的第一个颇具挑战性的Pattern。直到学习了Strategy之后,我才发现之前的认识是错误的——我混淆了Bridge与Strategy。现在,我认识到:
1. Bridge反映的是一组对象Abstraction与另一组对象Implementation之间的关系,Abstraction与Implementation分别有若干个派生类。
Strategy反映的是一个方法Method()与一组ConcreteStrategy对象之间的关系,这种关系需要Configuration对象的介入。
2. Bridge中Abstraction.Method()对应的可能是Implementation.Method_1()一个方法,也可能是Implementation.Method_1()+Implementation.Method_2()这样的组合;Implementation为Abstraction提供“方法的实现素材”,Abstraction.Method()不是简单地调用Implementation.Method(),Abstraction.Method()中可能还包括自己的一部分实现。
Strategy中Method()只能是对应某一个ConcreteStrategy.Method()。
3. Bridge中Abstraction.Method()与Implementation.Method()的对应关系是在设计时就确定了的。即假设派生于Abstraction的A.Method()被确定利用Implementation.Method_A()来实现其操作,那么无论这个Implementation是具体的Imp_One还是Imp_Two对象,A.Method()中都只能使用Imp_One或者Imp_Two的Method_A(),尽管Imp_One、Imp_Two可能还包括Method_B()之类的方法。
Strategy中Method()究竟与哪一个ConcreteStrategy.Method()对应是可以在运行时利用Configuration对象来改变映射关系的。
《Design Pattern Explained》一书中,使用不同版本的绘图设备Drawing(Implementation)绘制各种Shape(Abstraction)是理解Bridge Pattern很好的一个例子,作者也有很详尽的讲解。
posted on 2006-09-06 20:52 Abbey的网络日志 阅读(477)