码迷,mamicode.com
首页 > 其他好文 > 详细

理解策略模式

时间:2014-12-14 07:03:42      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:style   blog   io   ar   color   os   使用   sp   for   

  策略模式定义了算法族,不同的策略实现之间可以互相替换,让算法的变化独立于使用算法的客户。
这里的算法可以理解为对传入参数的处理或者某种行为。例如:如下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++模板的实现更为轻量级。

理解策略模式

标签:style   blog   io   ar   color   os   使用   sp   for   

原文地址:http://www.cnblogs.com/NotOnlyAnAnswer/p/4162167.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!