【Head First】 策略模式

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

一 策略模式的引入

         //参考Head First设计模式 - 策略模式 - 章节:设计模式入门

       假设要设计一个鸭子游戏系统,游戏要提供不同种类的鸭子供玩家选择,假设鸭子具备游泳,叫,飞和外观几个方法。 

      首先,想到的是继承,如下图:

 

        

        缺点:

        (1)可扩充性差、可复用性差、 后期维护困难 - 原因:代码大量重复 算法没有独立的封装;

            比如 实现了基类的fly(),记这个fly()为fly()1,fly()1在基类的派生类中被继承是可以的,但是若派生类需要其他的fly()方法呢?假设客户需要fly()2 fly()3 fly()4的算法,总不能给每个派生类都重新检查改写一遍吧..

        (2)灵活性差;

            比如 编译时,飞行、叫的方式在就决定了,不能在运行中决定。


二 策略模式的内容   

 

       三个设计原则:

  1. 封装可变 - 找出应用中需要变化之处,将其独立出来封装,使得变化部分与不变部分隔离;

  2. 接口编程 - 针对接口编程而不是针对实现编程,关键在于多态

  3. 多组合少继承 - 多用组合可以增加系统的弹性;

 

        类图:

        

 

解释:

Duck 抽象基类 - 抽象策略角色 

FlyBehavior 可变封装 - 具体策略角色

Quack 最终给客户端调用 - 环境角色

 

Duck类  FlyBehavior类 - 这是两个不同的类,前者封装应用中的不变部分;后者封装应用中的可变部分; - 这里体现了封装可变原则; 

 

 is-a继承关系:

MallardDuckDuck 的派生类 

FlyWithWings 是 FlyBehavior 的派生类 - 把FlyWithWings FlyNoWay看成算法,则体现了接口编程原则; - 而接口编程的关键 在于 多态

 

has-a组合关系:

Duck类中实例化了两个FlyBehavior类的变量 - has-a关系 - 这里体现了多组合少继承原则; 

 

 

 


三 策略模式 Duck C++实现

//Duck.h

#ifndef _DUCK_H_

#define _DUCK_H_

#include <iostream>

using namespace std;

class FlyBehavior{

public:

        virtual ~FlyBehavior(){};

        virtual void fly(){};

};

class FlyWithWings:public FlyBehavior{

public:

        virtual void fly() { cout << "I can fly with wings." << endl; }

};

class FlyNoWay :public FlyBehavior{

public:

        virtual void fly(){ cout << "I can not fly." << endl; }

};

class QuackBehavior{

public:

        virtual ~QuackBehavior(){};

        virtual void quack(){};

};

class Quack :public QuackBehavior{

public:

        virtual void quack(){ cout << "Quack. " << endl; }

};

class Squack :public QuackBehavior{

public:

        virtual void quack(){ cout << "Squack. " << endl; }

};

class MuteQuack :public QuackBehavior{

public:

        virtual void quack(){ cout << "No quack. " << endl; }

};

class Duck{

protected:

        FlyBehavior *flyBehavior;

        QuackBehavior *quackBehavior;

public:

        virtual ~Duck(){};

        void swim(){ cout << "All of us can swim. " << endl; }

        void performQuack(){ quackBehavior->quack(); }

        void performFly(){ flyBehavior->fly(); }

        virtual void display() = 0;

        void setFlyBehavior(FlyBehavior *fly){ flyBehavior = fly; }

        void setQuackBehavior(QuackBehavior *quack){ quackBehavior = quack; }

};

class MallardDuck :public Duck{

public:

        MallardDuck(FlyBehavior *fly, QuackBehavior *quack)

        {

               flyBehavior = fly;

               quackBehavior = quack;

        }

        virtual void display(){ cout << "I am a mallardDuck. " << endl; }

};

class RedheadDuck :public Duck{

public:

        RedheadDuck(FlyBehavior *fly, QuackBehavior *quack)

        {

               flyBehavior = fly;

               quackBehavior = quack;

        }

        void display(){ cout << "I am a duck of red head." << endl; }

};

class RubberDuck :public Duck{

public:

        RubberDuck(FlyBehavior *fly, QuackBehavior *quack)

        {

               flyBehavior = fly;

               quackBehavior = quack;

        }

        void display(){ cout << "I am a rubber duck." << endl; }

};

class DecoyDuck :public Duck{

public:

        DecoyDuck(FlyBehavior *fly, QuackBehavior *quack)

        {

               flyBehavior = fly;

               quackBehavior = quack;

        }

        void display(){ cout << "I am a decoy duck." << endl; }

};

#endif

 

//Duck_maincpp

#include "Duck.h"

int main()

{

        FlyBehavior *fly = new FlyNoWay();

        QuackBehavior *quack = new MuteQuack();

        //

        Duck *d = new MallardDuck(fly,quack);

        d->display();

        d->performFly();

        d->performQuack();

        delete fly;

        delete quack;

        cout << endl;

        fly = NULL;

        quack = NULL;

        fly = new FlyWithWings();

        d->setFlyBehavior(fly);

        d->performFly();

        delete d;

        d = NULL;

        system("pause");

        return 0;

}

 

 


四 敲代码中遇到的问题:

 

(1) 无法解析的外部符号 "public: virtual __thiscall FlyBehavior::~FlyBehavior(void)

 

原因:析构函数只声明,未定义。 如: 

class FlyBehavior{

public:

        virtual ~FlyBehavior();

        virtual void fly();

};

 解决:+个 {}

class FlyBehavior{

public:

        virtual ~FlyBehavior(){};

        virtual void fly(){};

};

 

(2)存疑:

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值