上篇博文中,我们系统的学习了下工厂模式,下面我们就来学习下另一个设计模式——策略模式,策略模式的定义:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。对于策略模式,用户只需要关注所选择的策略,不必关注具体的策略实现,从而实现了接口和实现相分离,说了这么多,感觉还是很模糊,还是从代码上下手吧,代码如下:
1)直接传递策略对象的方式
#ifndef __STRATEGY__H
#define __STRATEGY__H
#include <iostream>
#include <boost/smart_ptr.hpp>
using namespace std;
using namespace boost;
class goWork
{
public:
virtual void work() = 0;
};
class goWorkByBus : public goWork
{
public:
void work()
{
cout<<"go work by bus"<<endl;
}
};
class goWorkByBike : public goWork
{
public:
void work()
{
cout<<"go work by bike"<<endl;
}
};
class goWorkByFoot : public goWork
{
public:
void work()
{
cout<<"go work by foot"<<endl;
}
};
class WorkByWay
{
public:
WorkByWay(shared_ptr<goWork>& gowork):tool(gowork)
{
}
void work()
{
tool->work();
}
private:
shared_ptr<goWork> tool;
};
#endif
include "Strategy.h"
int main()
{
shared_ptr<goWork> gowork(new goWorkByBus());
WorkByWay workbyWay(gowork);
workbyWay.work();
shared_ptr<goWork> gowork1(new goWorkByBike());
WorkByWay workbyWay1(gowork1);
workbyWay1.work();
return 0;
}
用这种方式最大的问题就是:直接暴露了类的实现方式,因此,在此基础上人们又想出了另外的解决方案,就通过向目标对象传递标志的方式,代码如下:
#ifndef __STRATEGY__H
#define __STRATEGY__H
#include <iostream>
#include <boost/smart_ptr.hpp>
using namespace std;
using namespace boost;
class goWork
{
public:
virtual void work() = 0;
};
class goWorkByBus : public goWork
{
public:
void work()
{
cout<<"go work by bus"<<endl;
}
};
class goWorkByBike : public goWork
{
public:
void work()
{
cout<<"go work by bike"<<endl;
}
};
class goWorkByFoot : public goWork
{
public:
void work()
{
cout<<"go work by foot"<<endl;
}
};
enum WAY
{
BUS,
BIKE,
FOOT
};
class WorkByWay
{
public:
WorkByWay(WAY way)
{
switch(way)
{
case BUS:
tool= shared_ptr<goWork>(new goWorkByBus());
break;
case BIKE:
tool= shared_ptr<goWork>(new goWorkByBike());
break;
case FOOT:
tool= shared_ptr<goWork>(new goWorkByFoot());
break;
}
}
void work()
{
tool->work();
}
private:
shared_ptr<goWork> tool;
};
#endif
#include "Strategy.h"
int main()
{
WorkByWay workByWay1(BUS);
WorkByWay workByWay2(BIKE);
WorkByWay workByWay3(FOOT);
workByWay1.work();
workByWay2.work();
workByWay3.work();
return 0;
}
从上述代码中可以看到,其主要是通过传递了一个标记给目标对象,这样克服了直接将传递对象带来的一些不安全问题,并且使得用户不用太关心接口的具体实现,从而提高了类的封装性,接下来,我们再来看看如果采用模板的方式来实现的话,该如何做,这种方法,来标记都省略了,但是需要用户指明其使用的是哪个算法类,代码如下:
3)模板方式
#ifndef __STRATEGY__H
#define __STRATEGY__H
#include <iostream>
#include <boost/smart_ptr.hpp>
using namespace std;
using namespace boost;
class goWork
{
public:
virtual void work() = 0;
};
class goWorkByBus : public goWork
{
public:
void work()
{
cout<<"go work by bus"<<endl;
}
};
class goWorkByBike : public goWork
{
public:
void work()
{
cout<<"go work by bike"<<endl;
}
};
class goWorkByFoot : public goWork
{
public:
void work()
{
cout<<"go work by foot"<<endl;
}
};
template<class T>
class WorkByWay
{
public:
WorkByWay()
{
tool = shared_ptr<T>(new T());
}
void work()
{
tool->work();
}
private:
shared_ptr<goWork> tool;
};
#endif
#include "Strategy.h"
int main()
{
WorkByWay<goWorkByBus> workByWay1;
WorkByWay<goWorkByBike> workByWay2;
WorkByWay<goWorkByFoot> workByWay3;
workByWay1.work();
workByWay2.work();
workByWay3.work();
return 0;
}
其实模板方式还是很简单,只是最大的问题就是用户必须要指明算法的实现类名,这样也就等于暴露了相关类的实现,给用户带来了不必要的负担,所以个人还是比较喜欢第二种方式,因为在第二种方式中,其实它融合了工厂模式的设计思想。
总结
本篇博文主要是分析了设计模式中的策略模式,其实这种模式设计思想很简单,主要是根据根据不同的算法,实现相互之间的替换,上述的一些案例也是很简单的,其实要想用好策略模式,我们需要进行一些必要的练习,等有时间的话,自己也想写几个关于设计模式方面的应用案例,到时候在一起放在github里面吧,好了,本篇博文到此结束,下篇博文我们将继续分析下一个设计模式——适配器模式,尽情期待,多谢了,
如果需要,请注明转载,多谢