读书日记-策略模式

开始之前

  每次看书都会收获不一样的感受,走过的弯路越多回头来看前人整理的书籍,才发现原来都在上面。

框架写的越多,看起HeadFirst越能体会它的好。

策略模式定义

  定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户

设计原则

  1、找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

  2、针对接口编程,而不是针对实现编程。
  3、多用组合,少用继承。

这是书上的Tips,前人总结的准则,在设计系统应该多加参考。

案例

  在一个模拟鸭子游戏:SimUDuck。游戏中有各种鸭子,一边游泳戏水,一边呱呱叫。现在设计了一个Duck的类,并让各种鸭子继承此超类。

  

问题:现在新增了一个需求,需要让MallardDuck和RedheadDuck有飞的方法,同时新增一个DecoyDuck(诱捕鸟)子类不要飞的方法。

一般的做法:

  在Duck类里写一个Fly()方法,让子类继承。MuteDuck中覆盖去掉实现。但是,这是针对实现编程,且每多一个子类,便要多设置一次。

策略模式实现的做法:

  在将fly方法提出来,单独写一个接口类如下:

// 关于飞的接口类
class IFlyBehavior
{
    virtual void fly() =0 ;
} 
// 可以飞的实现 
class FlyWithWings:public IFlyBehavior
{
    virtual void fly() override{ printf("fly with  wings!");};
}
// 不能飞的实现 
class NoWingsFly:public IFlyBehavior
{
    virtual void fly() override{ printf("no fly!"); };
} 

  这里方便显示直接将实现也写在头文件定义里,一般复杂的实现要单独在cpp中实现,这样才不会导致编译生成过大。

在有了飞的方法类之后,我们只需要让Duck基类拥有IFlyBehavior对象,然后在新增的doFly()方法中调用即可。

class Duck
{
public:
    void quack();

    void swim();

    void display();

    void doFly();
protected:
    IFlyBehavior* m_pFlyBehavior;
}
void Duck::doFly()
{
    if(m_pFlyBehavior)
    {
        m_pFlyBehavior->fly();
    }
}

然后再子类的构造函数中分别继承的IFlyBehavior对象进行不同的赋值。

// 能飞的绿头鸭
MallarDuck::MallarDuck(void)
{
    m_pFlyBehavior = new FlyWithWings();
}
// 不能飞的橡胶鸭子
DecoyDuck::DecoyDuck(void)
{
    m_pFlyBehavior = new NoWingsFly();
}

 这样的设计,可以让飞行这一行为被其他非鸭子类对象复用。同时可以再新增新的行为,也不影响鸭子类的飞行行为。

结尾

  “有一个(拥有)” 可能比 “是一个”  更好。  这就是组合的好处了。

原文地址:https://www.cnblogs.com/stratrail/p/5034231.html