首先我们先来认识一下什么是策略模式,百度百科的定义是:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。看起来比较容易头晕吧,其实简单的以我自己的理解来讲就是将一个类中可能会引起变化的行为独立出来,让它变成一个接口的形式,当你需要用到这个接口的具体实现时,你再将这个接口实现。
如果你还不明白,那么我举个例子吧。如果你要设计一个汽车的类那么你可能会这样做:
<span style="font-size:18px;">class Car
{
public:Car()
{
}
~Car()
{
}
int Speed(void)//返回汽车的速度
{
return m_Speed;
}
private:
};</span>
但是问题出来了,汽车的种类不止一种每种汽车都有自己的速度,那你怎样实现一个类让每种汽车都满足呢?你可能首先想到的办法是将Speed变成一个虚函数或者纯虚函数,然后把Car当成是基类去继承,在派生类中去实现Speed的动态绑定就像这样:
class Car
{
public:
Virtual int Speed(void)=0;//纯虚函数
};
class Truck:public Car
{
virtual int Speed(void)
{
……
}
};
当然这的确是一种解决之道,现在看上去好像没什么大问题,但是我现在给你提另一个要求,要求你的车是可以变速的,根据档位的变化速度会发生变化,那你的Speed就需要一个档位参数,可是你的基类中并没有这个形式的实现,那你怎么办你是去基类中再去添加一个带档位参数的虚函数(virtual int Speed(int iStall)=0),还是你自己在派生类中去重载一个带档位参数的版本,我觉得这都不是好的做法。
现在我们来看看策略模式的做法,把可变的部分抽出来变成接口,这里可变的部分当然是Speed啦,我们把它抽象出来变成接口Speed类:
class Speed
{
public:
virtual int SpeedFix(void)
{
..…..
}
virtual int SpeedVariable(int iStall)
{
….
}
private:
};
把Car类变成:
Class Car
{
public:
private:
Speed *m_pSpeed;
};
如果有一辆卡车,他的普通时速是60Km,那么我们就这样来实现:
class TruckSpeed
{
public:
virtual int SpeedFix(void)
{
…………….
}
};
class Truck:public Car
{
public:
Truck(Speed *pSpeed)
:m_pSpeed(pSpeed)
{
}
int GetSpeedFix(void)
{
return m_pSpeed->SpeedFix();
}
};
Truck truck(new TruckSpeed);
你会说,这跟上面用虚函数的方法不是差不多嘛,而且代码还多了,如果你真的这么想的话那么你可以试试当Car的子类到达一定的数量时你再去看看你的代码,我相信,那应该已经复杂而庞大了。况且如果你的子类还去派生子类的话,我滴天哪,会发生什么你自己应该会想到。况且面向接口编程还有一个更大的优点:灵活。你可以在执行过程中随时随地的改变Speed的行为,而不改变子类原来的框架,甚至Car子类可以做到零修改。
好的,如果你了解了,你是不是应该知道了策略模式的好处了呢,好吧你也许还会抱怨,不想多写那么多的代码,还有没有更简单的做法,答案是当然有,用我们的bind和function这对神器。关于这对神器的用法,我这里就不详细讲了,可以自己去查现在的C++版本应该都将他们加入进来了。让我们改写Car类。
Class Car
{
public:
Car(std::tr1::function<int()> func_)
: SpeedFunc_(func_){}
int Speed(void)
{
if(SpeedFunc_)
return SpeedFunc_();
else
return 0;
}
private:
std::tr1::function<int()> SpeedFunc_;
}
不明所以的人要问了,这不跟第一种形式一样吗?不一样, SpeedFunc_ 已经是接口的形式了,至于怎么用下面举几个例子:
int SpeedFix(void)//非成员函数
{
………
}
Car car(std::tr::bind(&SpeedFix));
car.Speed();
如果要带参数怎么办呢?也没问题。
int SpeedVariable(int iStall)
{
……
}
Car car(std::tr::bind(&SpeedVariable,1))
car.Speed();
如果是类的成员函数呢?放心,也没问题。
class Speed
{
int GetSpeed(int iStall)
{
……
}
};
Speed speed;
Car car(std::tr::bind(&Speed::GetSpeed,&speed,1))
Car.Speed();
怎么样是不是不明觉厉啊,用function和bind手法取代传统的策略模式是不是非常的方便,而且节省了不少的代码量,真是我见过的最称手的黄金搭档。