策略模式定义:定义算法族,分别封装起来,让它们之间可以相互替换;此模式让算法的变化独立于使用算法的客户。
一 策略模式的引入
//参考Head First设计模式 - 策略模式 - 章节:设计模式入门
假设要设计一个鸭子游戏系统,游戏要提供不同种类的鸭子供玩家选择,假设鸭子具备游泳,叫,飞和外观几个方法。
首先,想到的是继承,如下图:
缺点:
(1)可扩充性差、可复用性差、 后期维护困难 - 原因:代码大量重复 算法没有独立的封装;
比如 实现了基类的fly(),记这个fly()为fly()1,fly()1在基类的派生类中被继承是可以的,但是若派生类需要其他的fly()方法呢?假设客户需要fly()2 fly()3 fly()4的算法,总不能给每个派生类都重新检查改写一遍吧..
(2)灵活性差;
比如 编译时,飞行、叫的方式在就决定了,不能在运行中决定。
二 策略模式的内容
三个设计原则:
- 封装可变 - 找出应用中需要变化之处,将其独立出来封装,使得变化部分与不变部分隔离;
- 接口编程 - 针对接口编程而不是针对实现编程,关键在于多态;
- 多组合少继承 - 多用组合可以增加系统的弹性;
类图:
解释:
Duck 抽象基类 - 抽象策略角色
FlyBehavior 可变封装 - 具体策略角色
Quack 最终给客户端调用 - 环境角色
Duck类 FlyBehavior类 - 这是两个不同的类,前者封装应用中的不变部分;后者封装应用中的可变部分; - 这里体现了封装可变原则;
is-a即继承关系:
MallardDuck 是 Duck 的派生类
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)存疑: