概要
策略模式主要针对那种,有多种算法和可能的项目情况, 比如说一个人去旅行,然后可以有多种方式选择, 坐飞机, 坐火车, 坐轮船, 然后每一种方式又有各自的价格, 所花费的时间, 能在哪里去坐。 这时,我们又需要做出选择。
又比如另外一种情况, 公司做一款游戏, 比如说来画鸭子, 需求是鸭子声音有大的,有小的, 鸭子有飞得高的,有飞得低的,而且还需要可任意组合,这时就要求我们选择对应的策略,下面的简单例子就是针对这个的。
效果图
策略1
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Duck *duck = new Duck(new HightFly(), new HeightVoice());
// Duck *duck = new Duck(new LowFly(), new HeightVoice());
// Duck *duck = new Duck(new LowFly(), new LowVoice());
// Duck *duck = new Duck(new HightFly(), new LowVoice());
duck->fly();
duck->voice();
return a.exec();
}
策略2
// Duck *duck = new Duck(new HightFly(), new HeightVoice());
Duck *duck = new Duck(new LowFly(), new HeightVoice());
// Duck *duck = new Duck(new LowFly(), new LowVoice());
// Duck *duck = new Duck(new HightFly(), new
LowVoice());
策略3
// Duck *duck = new Duck(new HightFly(), new HeightVoice());
// Duck *duck = new Duck(new LowFly(), new HeightVoice());
Duck *duck = new Duck(new LowFly(), new LowVoice());
// Duck *duck = new Duck(new HightFly(), new
LowVoice());
策略4
// Duck *duck = new Duck(new HightFly(), new HeightVoice());
// Duck *duck = new Duck(new LowFly(), new HeightVoice());
// Duck *duck = new Duck(new LowFly(), new LowVoice());
Duck *duck = new Duck(new HightFly(), new
LowVoice());
主要代码
//duck.h
#ifndef DUCK_H
#define DUCK_H
#include "flyhavior.h"
#include "voicehavior.h"
#include "lowfly.h"
#include "heightvoice.h"
class Duck
{
public:
Duck(FlyHavior* flyHavior, VoiceHavior* voiceHavior);
void fly();
void voice();
void setFlyHavior(FlyHavior* flyHavior);
void setVoiceHavior(VoiceHavior* voiceHavior);
private:
FlyHavior *m_flyHavior;
VoiceHavior *m_voiceHavior;
};
#endif // DUCK_H
//duck.cpp
#include "duck.h"
Duck::Duck(FlyHavior* flyHavior, VoiceHavior* voiceHavior)
:m_flyHavior(flyHavior),
m_voiceHavior(voiceHavior)
{
}
void Duck::fly()
{
m_flyHavior->fly();
}
void Duck::voice()
{
m_voiceHavior->voice();
}
void Duck::setFlyHavior(FlyHavior* flyHavior)
{
m_flyHavior = flyHavior;
}
void Duck::setVoiceHavior(VoiceHavior* voiceHavior)
{
m_voiceHavior = voiceHavior;
}
//flyhavior.h
#ifndef FLYHAVIOR_H
#define FLYHAVIOR_H
#include <iostream>
using namespace::std;
class FlyHavior
{
public:
FlyHavior();
virtual ~FlyHavior();
virtual void fly();
};
#endif // FLYHAVIOR_H
//flyhavior.cpp
#include "flyhavior.h"
FlyHavior::FlyHavior()
{
}
FlyHavior::~FlyHavior()
{
}
void FlyHavior::fly()
{
}
//voicehavior.h
#ifndef VOICEHAVIOR_H
#define VOICEHAVIOR_H
#include <iostream>
using namespace::std;
class VoiceHavior
{
public:
VoiceHavior();
virtual ~VoiceHavior();
virtual void voice();
};
#endif // VOICEHAVIOR_H
//voicehavior.cpp
#include "voicehavior.h"
VoiceHavior::VoiceHavior()
{
}
VoiceHavior::~VoiceHavior()
{
}
void VoiceHavior::voice()
{
}
//lowfly.h
#ifndef LOWFLY_H
#define LOWFLY_H
#include "flyhavior.h"
class LowFly : public FlyHavior
{
public:
LowFly();
void fly();
};
#endif // LOWFLY_H
//lowfly.cpp
#include "lowfly.h"
LowFly::LowFly()
{
}
void LowFly::fly()
{
cout << "LowFly::LowFly()" << endl;
}
//hightfly.h
#ifndef HIGHTFLY_H
#define HIGHTFLY_H
#include "flyhavior.h"
class HightFly : public FlyHavior
{
public:
HightFly();
void fly();
};
#endif // HIGHTFLY_H
//hightfly.cpp
#include "hightfly.h"
HightFly::HightFly()
{
}
void HightFly::fly()
{
cout << "HightFly::HightFly()" << endl;
}
部分解析
上面的主要代码是把鸭子duck作为客户端,在初始化对象时,可以进行属性的选择,如main函数里面的:
Duck *duck = new Duck(new HightFly(), new HeightVoice());
// Duck *duck = new Duck(new LowFly(), new HeightVoice());
// Duck *duck = new Duck(new LowFly(), new LowVoice());
// Duck *duck = new Duck(new HightFly(), new
LowVoice());
而duck的初始化函数为:
Duck::Duck(FlyHavior* flyHavior, VoiceHavior* voiceHavior)
:m_flyHavior(flyHavior),
m_voiceHavior(voiceHavior)
{
}
FlyHavior 是飞得高或低的父类,HightFly, LowFly 这两个类都继承于FlyHavior
VoiceHavior 是声音大还是小的父类, HeightVoice, LowVoice这两个类都继承于VoiceHavior
在两个父类中, 它们的析构函数都为虚函数,这样是为了防止内存泄漏。
比如这么一种情况:
VoiceHavior *voiceHavior = new HeightVoice();
delete voiceHavior;
如果VoiceHavior的构造函数不为虚函数,则会出现只进行父类的析构,而不进行子类的析构, 但如果VoiceHavior 构造函数为虚函数,则父类与子类同时析构。
再来看,我们把飞得高低的属性和声音大小的属性抽象了两个属性
VoiceHavior , FlyHavior ,需要增加其它的策略则直接继承于它们,这样就减少了条件语句的判断。
在进行属性设置时,采用了上下转型的方式把子类的对象进行父类的向上转型,这样就可以达到简单方便地切换各个属性。