(二)java设计模式之策略模式

来源:互联网 发布:魔笛 知乎 编辑:程序博客网 时间:2024/05/17 07:49

我们在实际的开发过程中可能会遇到这样的情况,同一个业务逻辑,在不同的外在条件下,需要使用不同的算法来实现,如果这时把各种功能的算法都堆砌到同一个类中,会做各种判断,然后再实现不同的算法功能,这样的代码一定非显得非常庞杂。



策略模式就是针对复杂业务逻辑功能,实现特定算法的封装,就是底层算法的实现和客户端完全的解耦。这样业务逻辑无论做怎样的修改,客户端都不用关心。策略模式实质上就是封装了变化。


下面上代码分析,一个商场促销打折的例子。
业务背景:商场中的商品可能会根据不同的节日进行打折促销活动,本demo是根据商品实际的金额经过特定的促销策略后,得出一个最终的价格。



1、创建出打折策略的抽象接口,定义出策略的抽象行为。

public interface ICash {    public double getCashResult(double money);}

2、根据不同过的打折策略,分别实现策略接口。

//不打折,正常收费的算法(策略)public class CashNomal implements ICash {    @Override    public double getCashResult(double money) {        return money;    }}//打特定的折扣的算法(策略)public class CashRebate implements ICash {    private double rate = 1;    public CashRebate(double rate) {        this.rate = rate;    }    @Override    public double getCashResult(double money) {        return money * rate;    }}//满减算法(策略)public class CashReturn implements ICash {    private double moneyCondition = 0;    private double moneyReturn = 0;    public CashReturn(double moneyCondition,double moneyReturn){        this.moneyCondition = moneyCondition;        this.moneyReturn = moneyReturn;    }    @Override    public double getCashResult(double money) {        double result = money ;        if(money > moneyCondition){            result = (moneyCondition%money)*moneyReturn;        }        return result;    }}

3、创建出上下文(有一种承上启下的作用),策略模式的关键,封装变化,对外只暴露统一接口

public class ContextStrategy {    private ICash cashStatery;    public ContextStrategy(ICash cashStatery){        this.cashStatery = cashStatery;    }    //对外暴露的统一接口,封装了策略    public double getFinalResult(double money){        return cashStatery.getCashResult(money);    }}

4、测试代码

public static void main(String[] args) {    ICash cashStatery = null;    switch (statery) {//判断使用那种具体策略    case "正常收费":        cashStatery = new CashNomal();        break;    case "打7折":        cashStatery = new CashRebate(0.7);        break;    case "满300减100":        cashStatery = new CashReturn(300,100);        break;    default:        break;    }    //将策略传入上下文    ContextStrategy cxStatery = new ContextStrategy(cashStatery);    double result = cxStatery.getFinalResult(500);}

5、优化,看到测试代码中还是需要使用switch来做各种判断,这样显得前端的代码特别繁琐,封装的不够彻底,应该把创建特定策略对象的任务封装起来,怎么办呢?可以引用简单工厂模式(上一篇博文,学以致用嘛),创建对象的工作交给工厂来做。客户端只需要传入特定的策略标识就OK。首先创建出工厂。

public class CashFactory {    //构造方法略,构造方法的作用是给策略使用到的一些数据赋值,比如满多少减多少等,为了方便下面直接传入了具体数值    public ICash getCashObj(String statery){        ICash cashStatery = null;        switch (statery) {//判断使用那种具体策略        case "正常收费":            cashStatery = new CashNomal();            break;        case "打折":            cashStatery = new CashRebate(0.7);            break;        case "满减":            cashStatery = new CashReturn(300,100);            break;        default:            break;        }        return cashStatery;    }}

修改策略上下文中的代码:

public class ContextStrategy {    private ICash cashStatery;    public ContextStrategy(ICash cashStatery){        this.cashStatery = cashStatery;    }    //扩展了一种创建策略上下文的方式,直接传入策略标识,由工厂来创建出特定的策略对象    public ContextStrategy(String strategy){//传入具体的策略字符串        this.cashStatery = new CashFactory().getCashObj(strategy);    }    public double getFinalResult(double money){        return cashStatery.getCashResult(money);    }}

如果这样修改的话,测试代码就可以这么写了:

public static void main(String[] args) {        ICash cashStatery = null;        //将策略标识传入上下文        String strategy = "满减";        ContextStrategy cxStatery = new ContextStrategy(strategy);        double result = cxStatery.getFinalResult(500);    }

6、总结:

  • 策略模式是一种定义了一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
  • 在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。


    [注:学习模板为-大话设计模式 程杰]
原创粉丝点击