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

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



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


下面上代码分析,一个商场促销打折的例子。
业务背景:商场中的商品可能会根据不同的节日进行打折促销活动,本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对象。


    [注:学习模板为-大话设计模式 程杰]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值