首页 > 代码库 > 理解策略模式

理解策略模式

  策略模式定义了算法族,不同的策略实现之间可以互相替换,让算法的变化独立于使用算法的客户。
这里的算法可以理解为对传入参数的处理或者某种行为。例如:如下java代码,对字符串实现不同的比较策略,Formatter类与CompareStrategy策略接口相依赖。可以使自身能够有对字符串的不同处理。

public interface CompareStrategy {    boolean less(String str1, String str2);}public class SizeCmpStrategy implements CompareStrategy {    @Override    public boolean less(String str1, String str2) {        return str1.length() < str2.length();    }}public class IgnoreCaseCmpStrategy implements CompareStrategy {    @Override    public boolean less(String str1, String str2) {        return str1.compareToIgnoreCase(str2) < 0;    }}public class Formatter {    private CompareStrategy cmp;    public CompareStrategy getCmp() {        return cmp;    }    public void setCmp(CompareStrategy cmp) {        this.cmp = cmp;    }}

  通常可以通过继承,重写父类的方法,使不同子类具有多态的行为。策略模式可以提供了替代继承的另一种方法。如果我们需要具备不同功能的类,我们可以不必总是通过继承某一父类实现不同的行为。而是通过注入不同的Strategy使其可以具备不同的行为。再举一个例子:

在一个游戏的角色随着升级的过程中,不同等级的英雄有不同的攻击和防守。可以将这变化的攻击和防守进行封装。如下面的Java代码:

public interface Attack {    void attack();}public interface Defend {    void defend();}public class PrimaryAttack implements Attack {    @Override    public void attack() {        System.out.println("初级进攻");    }}public class PrimaryDefend implements Defend {    @Override    public void defend() {        System.out.println("初级防守");    }}public class SeniorAttack implements Attack {    @Override    public void attack() {            System.out.println("高级进攻");    }}public class SeniorDefend implements Defend {    @Override    public void defend() {        System.out.println("高级防守");    }}public class Hero {    private Attack attack;    public Attack getAttack() {        return attack;    }    public void setAttack(Attack attack) {        this.attack = attack;    }    private Defend defend;    public Defend getDefend() {        return defend;    }    public void setDefend(Defend defend) {        this.defend = defend;    }    public void doAttack() {        attack.attack();    }    public void doDefend() {        defend.defend();    }    public static void main(String[] args){        Hero hero=new Hero();        hero.setAttack(new PrimaryAttack());        hero.setDefend(new PrimaryDefend());        hero.doAttack();        hero.doDefend();        System.out.println("升级啦");        hero.setAttack(new SeniorAttack());        hero.setDefend(new SeniorDefend());        hero.doAttack();        hero.doDefend();    }}

//程序输出:
/*
初级进攻
初级防守
升级啦
高级进攻
高级防守
*/ 

  由上述的例子,我们可以得出策略模式优点:这是一种可以替代继承的方法。并且这种行为是可以动态改变的并且不像继承一样硬编码。

2. C++模板和策略模式

  上述Java实现,C++可以很方便的进行类似的实现。这里再介绍一下基于C++模板的策略模式实现。

  C++的模板编程可以作为另外一种策略模式的实现,并且可能是更好的实现。将Strategy作为模板参数,开发出更为方便(隐式接口),高效率(编译期绑定)的程序。如:

#include <iostream>class PrimaryAttack{public:    void attack(){        std::cout<<"进行初级进攻"<<std::endl;    }};class PrimaryDefend{public:    void defend(){        std::cout<<"进行初级防守"<<std::endl;    }};class SeniorDefend{public:    void defend(){        std::cout<<"进行高级防守"<<std::endl;    }};class SeniorAttack{public:    void attack(){        std::cout<<"进行高级进攻"<<std::endl;    }};template<typename Attack, typename Defend>class Hero{public:    Hero():attack(),defend(){}    void doAttack()    {        attack.attack();    }    void doDefend(){        defend.defend();    }private:    Attack attack;    Defend defend;};int main(){    std::cout<<"我是初级英雄"<<std::endl;    Hero<PrimaryAttack, PrimaryDefend> primary_hero;    primary_hero.doAttack();    primary_hero.doDefend();    std::cout<<"我是高级英雄"<<std::endl;    Hero<SeniorAttack, SeniorDefend> senior_hero;    senior_hero.doAttack();    senior_hero.doDefend();}//程序输出:/*我是初级英雄进行初级进攻进行初级防守我是高级英雄进行高级进攻进行高级防守*/

 Note:由于模板属于编译时多态,因此行为属于编译期绑定,不能像之前Java实现那样对策略进行动态的改变。

  使用模板实现策略模式,带来了代码的简洁,不再需要定义接口,再进行实现。由于C++模板编程隐式接口约定,因此需要以文档的形式对策略的设计进行规定,如规定 Attack, Defend类型参数必须实现attack(),defend()方法。

与基于C++模板的策略模式相比,Java的实现比较繁琐,基于C++模板的实现更为轻量级。

理解策略模式