策略模式:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
继承自基类的派生类之间有许多不同的特点,比如鹦鹉继承自鸟类,但是颜色各有不同。可以在基类中定义一个虚函数,每个派生类中分别实现,这种方法使得代码重复,代码量变大,且增加维护成本。
策略模式的方法为定义算法族,算法族继承自算法族基类,对象基类中利用多态性增加指向算法族基类指针。创建不同派生类时,将算法族指针指向不同的算法,使得代码重复得到解决。并且可以动态的改变算法族指针,使得派生类在运行时可以动态的改变行为。
例:
mallardDuck,modelDuck,miniDuck均继承自基类Duck,三者会不会飞的行为各有不同,定义基类Duck,其中fly*为指向算法族基类的指针,通过flying()函数调用flyBehavior()函数。在Duck类中我们不关心派生类中的flyBehavior具体实现,实现交给算法族处理。
//Duck.h
#include <stdio.h>
#include "fly.h"
class Duck{
public:
fly* flyBeh;//算法族基类指针
Duck(){
flyBeh = new flyWithWings();//将flyBeh指向flyWithWings类
}
~Duck(){}
void move(){
printf("move\n");
}
void flying(){
flyBeh->flyBehavior();//flyBehavior为算法族基类fly类中定义的纯虚函数
}
void setFlyBehavior(fly* flyBehavior){
flyBeh = flyBehavior;//通过设置flyBeh指向算法组中不同的算法以在运行时动态的改变行为。
}
};
fly.h为算法族,派生类均继承自fly基类,实现flyBehavior方法。使得在算法族中又三种不同的飞行方式。三种方式均可由指向fly类型的指针调用。
//fly.h
#ifndef ________fly__
#define ________fly__
#include <stdio.h>
class fly{
public:
virtual void flyBehavior()=0;
};
class flyWithWings : public fly{
//分别实现flyBehavior方法
void flyBehavior(){
printf("flyWithWings\n");
}
};
class flyNoWay : public fly{
void flyBehavior(){
printf("flyNoWay\n");
}
};
class flyWithRocket : public fly{
void flyBehavior(){
printf("flyWithRocket\n");
}
};
在三种鸭子的构造函数中,使flyBeh指向不同的算法即可实现不同鸭子的不同飞行方式
//MallardDuck.h
#ifndef ________MallardDuck__
#define ________MallardDuck__
//绿头鸭
#include <stdio.h>
#include "Duck.h"
#include "fly.h"
class MallardDuck:public Duck, public flyWithWings{
public:
MallardDuck(){
flyBeh = new flyWithWings();//指向用翅膀飞行算法
}
};
//ModelDuck.h
#ifndef ________ModelDuck__
#define ________ModelDuck__
#include <stdio.h>
#include "Duck.h"
#include "fly.h"
class ModelDuck:public Duck,public flyNoWay{
public:
ModelDuck(){
flyBeh = new flyNoWay();//模型鸭子指向不能飞行
}
};
//MiniDuck.h
#ifndef ________MiniDuck__
#define ________MiniDuck__
#include <stdio.h>
#include "Duck.h"
#include "fly.h"
class MiniDuck:public Duck,public flyNoWay{
public:
MiniDuck(){
flyBeh = new flyNoWay();//mini鸭指向不能飞行
}
};
#endif /* defined(________MiniDuck__) */
主函数:
//main.h
#include <iostream>
#include "Duck.h"
#include "MallardDuck.h"
#include "ModelDuck.h"
#include "MiniDuck.h"
#include "fly.h"
int main(int argc, const char * argv[]) {
auto duck = new Duck();
printf("duck\n");
duck->move();
duck->flying();
printf("\n\n");
printf("mallardDuck\n");
auto mallardDuck = new MallardDuck();
mallardDuck->flying();//绿头鸭的飞行方式
printf("\n\n");
printf("modelDuck\n");
auto modelDuck = new ModelDuck();
modelDuck->flying();//模型鸭的飞行方式
modelDuck->setFlyBehavior(new flyWithRocket());//运行是动态的改变飞行方式
modelDuck->flying();
printf("\n\n");
printf("miniDuck\n");
auto miniDuck = new MiniDuck();
miniDuck->flying();
printf("\n\n");
return 0;
}
输出:
duck
move
flyWithWings
mallardDuck
flyWithWings
modelDuck
flyNoWay
flyWithRocket (动态的改变了飞行方式)
miniDuck
flyNoWay
总结:
策略模式把应用中需要变化的内容抽出来,使用算法族的方式实现,在创建对象时在算法族中挑选算法,最后组装成一个完整的对象。
设计原则:
找出应用中可能需要变化之处,把他们独立出来,不要和那些不用变化的代码混合在一起。
针对接口编程,而不是针对实现编程。