1. 策略模式

来源:互联网 发布:unity3d 给模型加动画 编辑:程序博客网 时间:2024/06/06 19:41
     开篇讲了学习本书的方法,从脑神经角度讲解了本书图文结合的布局,目的是更加有助于读者识记,使得生涩难懂的设计模式学起来轻松了许多。并讲解了应该如何去读懂这本书,可以一句话概括,就是要与书“交谈”,和多思考。本书从本书的排版设计到内容设计,无不表现了作者的精心策划。例如第一章举出各种鸭子具有不同行为的例子,循序渐进地引出了策略模式这个概念。
     首先提出新的需求,在duck身上添加fly功能,(1)最初会想到方法就是在duck类中添加一个成员函数fly(),但是这种方法很糟糕,这会导致每种具体的duck对象也继承了fly的功能,但这是不合理的改变,对于每种具体的duck需要override覆盖基类的fly(),一些duck具有一种fly的方法,另一些duck具有另一种fly方法时,也需要对每种具体的duck重复写fly方法,按照这种方法,当需要duck具有更多新的行为时,直接在duck上添加新的行为,就会带来许多重复的代码,不具备良好的OO设计特性。(2)之后就想到了在(1)的基础上的改进办法,创建fly和quack的接口类,只需对于那些可以fly的duck实现fly方法,这样做虽然可以使不具有飞行为的duck不用override飞的方法,但是一些fly行为发生变化时,就需要改变多个具体duck中的fly方法,所以不易于维护代码。(3)在(2)的基础上,将行为类进行抽象,分离其中变化和不变的部分。当要添加新fly方法,只需要继承抽象的fly类,创建一个新的具体fly类,有易于扩展代码。且将行为类从具体类中抽象出来可以方便对行为类的复用,不仅仅对duck,如果有其他的animal也具有fly的能力,那么有可能可以对fly行为进行复用。
     在我看来,策略模式的精髓在于定义一个算法(行为)族,将具体类和算法类进行分离,具体类可以对自己所拥有的算法对象相互替换。具体类在初始化时,在构造器中new出来算法对象,在程序的运行中具体类能够替换算法。例如表现一只会飞的鸭子,时而飞,时而停歇,这时就需要替换算法,飞时有飞行为的对象,停时有不飞行为的对象,他们都有一个fly接口实现具体行为。
     这个算法体现了三个突出的面向对象的原则。其一,变化与不变化分离,封装变化。将飞行为抽象出来创建一个抽象的flybehavior类,由它衍生出来各种飞的具体行为类。抽象的flybehavior类是不改变的,各种飞的具体行为类是可能变动的,可以进行不断扩展。其二,基于接口的编程,而不是基于实现编程。对于扩展的飞的具体类,只需要实现具体的飞行为类 (接口类),其他的不需要改动,duck有一个flybehavior对象,duck委托给它处理各种fly行为。其三,尽量多用组合,而不是继承。这一点表现在duck有一个flybehavior对象,具体的duck不是继承flybahavior,组合的好处在于可以在运行时替换算法(各种飞行为),具体的duck不需要处理各种fly行为。将各种行为设计为算法族的设计突出了它具有复用性、扩展性和易于维护性(良好的OO设计特点)。


class Duck{public:     void PerformFly() ;     void PerformQuack() ;     void SetFlyBehavior(FlyBehavior *fly) ;     void SetQuackBehavior(QuackBehavior *quack);private:     FlyBehavior *fly;     QuackBehavior *quack;};void Duck::PerformFly() {    fly->Fly();}void Duck::PerformQuack() {    quack->Quack();}void Duck::SetFlyBehavior(FlyBehavior *fly) {     fly = fly;}void Duck::SetQuackBehavior(QuackBehavior *quack) {     quack = quack;}

client:DuckA *duck = new DuckA();FlyWithWings *fly = new FlyWithWings();duck->SetFlyBehavior(fly);duck->PerformFly();