strategy模式
这次遇到它不是在项目中,但项目也有的。。今天实际上发现,在项目中23种设计模式的基本用法都作了示例。。原型也都规定好了。。
策略模式是在读ThoughtWork文集里看到的,还提及了Null Object模式,两个都大致说下。
The strategy pattern is intended to provide a means to define a family of algorithms, encapsulate each one as an object, and make them interchangeable. The strategy pattern lets the algorithms vary independently from clients that use them. 这样我们可以运行里,切换算法的实现。
上图(from wiki):
实际上,在一些情况下,我们已经不自觉的在使用这一模式了,不知道你是不是也有同感。
再来一段示例代码:
#include <iostream>
using namespace std;
class StrategyInterface
{
public:
virtual void execute() const = 0;
};
class ConcreteStrategyA: public StrategyInterface
{
public:
virtual void execute() const
{
cout << "Called ConcreteStrategyA execute method" << endl;
}
};
class ConcreteStrategyB: public StrategyInterface
{
public:
virtual void execute() const
{
cout << "Called ConcreteStrategyB execute method" << endl;
}
};
class ConcreteStrategyC: public StrategyInterface
{
public:
virtual void execute() const
{
cout << "Called ConcreteStrategyC execute method" << endl;
}
};
class Context
{
private:
StrategyInterface * strategy_;
public:
explicit Context(StrategyInterface *strategy):strategy_(strategy)
{
}
void set_strategy(StrategyInterface *strategy)
{
strategy_ = strategy;
}
void execute() const
{
strategy_->execute();
}
};
int main(int argc, char *argv[])
{
ConcreteStrategyA concreteStrategyA;
ConcreteStrategyB concreteStrategyB;
ConcreteStrategyC concreteStrategyC;
Context contextA(&concreteStrategyA);
Context contextB(&concreteStrategyB);
Context contextC(&concreteStrategyC);
contextA.execute(); // output: "Called ConcreteStrategyA execute method"
contextB.execute(); // output: "Called ConcreteStrategyB execute method"
contextC.execute(); // output: "Called ConcreteStrategyC execute method"
contextA.set_strategy(&concreteStrategyB);
contextA.execute(); // output: "Called ConcreteStrategyB execute method"
contextA.set_strategy(&concreteStrategyC);
contextA.execute(); // output: "Called ConcreteStrategyC execute method"
return 0;
}
好,下面说Null Object模式,很容易,先上代码:
class animal {
public:
virtual void make_sound() = 0;
};
class dog : public animal {
void make_sound() { cout << "woof!" << endl; }
};
class null_animal : public animal {
void make_sound() { }
};
你一定不知道这段代码有什么神奇的地方,那就听我慢慢说。
在一些场合下,假设我们需要传一个引用参数,这没什么,但要说明这个引用可能为“空”。好,怎么表示这个空?Java中没有问题,null就搞定了;那C++这种东西呢? 当然我们可以说用指针来绕过这一问题,但你对这个答案满意么?
好,我们看看这段代码,把null_animal这个东西认为是一个类似NULL的东西如何呢?
这种做法不但可以解决问题,还会有一些其它的好处。
比如,当然类型是一个数组(比如java中的list)时,我们可能要对返回值为null的情形特殊处理,但如果返回这样一个无害的对象,其iterator可以正常调用但不会产生什么实际效果,这样是不是更好呢?
这样的用法,至少可以减少分支(if else)数,使方法的代码行数减少,结构明析。
再一点好处,我们可以把这种对象作为桩来用--万一我们的测试还差一部分才能做,而这一部分一时半会儿完不成但我们暂时用不太到时。


浙公网安备 33010602011771号