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):

 780px-Strategy_Pattern_Diagram_ZP.svg

实际上,在一些情况下,我们已经不自觉的在使用这一模式了,不知道你是不是也有同感。

再来一段示例代码:

#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)数,使方法的代码行数减少,结构明析。

再一点好处,我们可以把这种对象作为桩来用--万一我们的测试还差一部分才能做,而这一部分一时半会儿完不成但我们暂时用不太到时。

posted @ 2010-12-13 03:27  justin_s  阅读(277)  评论(0编辑  收藏  举报