首先什么是“策略模式”:定义了算法家族,分别封装起来,让他们之间可以相互替换,让算法的变化,不会影响到使用算法的客户。(大话设计模式P23)


我们先来看看策略模式的UML类图是怎样的。

大话设计模式学习笔记-策略模式(c++描述)_面向对象


1、其中Context类利用ConcreteStrategy类来配置,维护Strategy的引用

2、Strategy类是算法的公共接口

3、ConcreteStrategy类则实现了算法的行为


注意:其中Context类和Strategy类是一种“聚合关系”,是一种弱的拥有关系,其与组合关系的区别是:组合关系是一种强的拥有关系,组合关系中相互之间的生命周期是相同的。而聚合关系则不要求,我的理解是:Context可以有Strategy,但是即使不存在Context,Strategy本身也是可以存在的。其中的细微差别需要好好品味。


代码实现:

为简便我省略掉头文件和命名空间的声明。

//Context
class Context {
public:
    Context(Strategy* s) : strategy(s) {}
    void ContextInterface() {
        strategy->AlgorithmInterface();
    }
private:
    Strategy *strategy;
};


//Strategy
class Strategy {
public:
    virtual void AlgorithmInterface() = 0;
};
//ConcreteStrategyA
class ConcreteStrategyA : public Strategy {
public:
    void AlgorithmInterface() {
        //do A
    }
};
//ConcreteStrategyB
class ConcreteStrategyB  : public Strategy {
public:
    void AlgorithmInterface() {
        //do B
    }
};


客户端:

int main() {
    //以下代码只作示范使用,实际上用new产生的对象是在heap中的
    //所以第二次new的时候,第一次产生的对象不会自动删除,因此会产生内存泄露
    //我们可以手动delete,或者利用智能指针来解决
    Strategy *s = new ConcreteStrategyA();
    Context *c = new Context(s);
    c->ContextInterface();
    s = new ConcreteStrategyB();
    c = new Context(s);
    c->ContextInterface();
    return 0;
}


下面我找个例子来试验一下:游戏中根据选择的职业不同,攻击方式也会不同

游戏角色类

//游戏角色类
class Player {
public:
    Player(Character* c) : pChar(c) {}
    void action() {
        pChar->attack();
    }
private:
    Character *pChar;
};


职业类

//职业类接口
class Character {
public:
    virtual void attack() = 0;
};
//剑士
class Saber : public Character {
public:
    void attack() {
        cout << "斩击" << endl;
    }
};
//弓箭手
class Archer : public Character {
public:
    void attack() {
        cout << "射击" << endl;
    }
};
//魔法师
class Caster : public Character {
public:
    void attack() {
        cout << "火球术" << endl;
    }
};


客户端

int main() {
    Player *player;
    cout << "魔法师攻击: ";
    player = new Player(new Caster());
    player->action();
                    
    cout << "剑士攻击: ";
    player = new Player(new Saber());
    player->action();
    return 0;
}


大话设计模式学习笔记-策略模式(c++描述)_策略模式_02


策略模式有助于我们应对算法行为的变化,例如上述的例子中,如果我们增加新的职业,我们只需要添加新职业的类,之后在人物当中配置新职业的类,我们就可以应对这种变化。