在上一篇文章里,我们了解了简单工厂设计模式之后,接下来我们要说的是策略设计模式。
首先看一下策略模式(Strategy)的正式定义:它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化不会影响到使用算法客户。
如果你感觉看完这段定义之后,有些困惑或者不理解,没关系,我会逐步引导,让你找到一点点拨云见日的感觉。
还是要用到前面的简单工厂设计模式来做引导,在那个模式里面,我们在测试环节传入的参数代表什么?答案是加减乘除的符号,通俗的讲传入的是能根据该符号判断产生对应的entity对象的标志,接着根据这个产生的entity对象,调用里面定义的方法进行运算得到我们需要的结果值,将结果值返回到测试环节中,然后将结果值打印显示。在这里我们的首要目的是得到entity对象,因为对象里面定义了获得结果方法。
而策略模式,我们需要首先得到的是什么?答案就是解决需求的具体策略。而策略里面同样是定义了解决问题的方法,听起来是不是感觉两者很像。好了,我们来试试代码吧。代码过后我们再做一些对比总结。
我们依旧是采用Java面向对象的思想来实现。
1、定义抽象策略父类:
package main_operation; /** * 策略父类 * Created by Administrator on 2017/8/1. */ public abstract class CashSuperStrategy { /** * 定义一个抽象的策略方法 * @param payment 消费额 * @return */ public abstract double acceptCash(double payment); }
2、定义对应的具体策略执行类
无优惠支付策略类:
package entity; import main_operation.CashSuperStrategy; /** * Created by Administrator on 2017/8/1. */ public class CashNormal extends CashSuperStrategy { /** * 定义具体的策略执行方法 * @param payment 消费额 * @return */ @Override public double acceptCash(double payment) { return payment; } }
打折策略执行类:
package entity; import lombok.AllArgsConstructor; import main_operation.CashSuperStrategy; /** * Created by Administrator on 2017/8/1. */ @AllArgsConstructor public class CashRebate extends CashSuperStrategy { /** * 打折率 */ private double discount = 1; @Override /** * 定义具体的策略执行方法 */ public double acceptCash(double payment) { return payment * discount; } }
满减策略执行类
package entity; import lombok.AllArgsConstructor; import main_operation.CashSuperStrategy; /** * Created by Administrator on 2017/8/1. */ @AllArgsConstructor public class CashReturn extends CashSuperStrategy { /** * 满减额度中满的值 */ private double discountCondition; /** * 满减额度中减的值 */ private double moneyReturn; @Override /** * 定义具体的策略执行方法 */ public double acceptCash(double payment) { double actualPayment = payment; if (payment >= discountCondition){ actualPayment = payment - Math.floor(payment/discountCondition)* moneyReturn; } return actualPayment; } }
3、定义一个策略枚举
package enum_entity; /** * Created by Administrator on 2017/8/1. */ public enum CashCondition { /** * 构造对应策略的枚举值 */ NORMAL,MONEY_RETURN,REBATE; }
4、定义策略开关类
package controller; import entity.CashNormal; import entity.CashRebate; import entity.CashReturn; import enum_entity.CashCondition; import main_operation.CashSuperStrategy; /** * Created by Administrator on 2017/8/1. */ public class CashContext { private CashSuperStrategy strategy; /** * 通过传入枚举值,判断选用何种策略 * @param condition */ public CashContext(CashCondition condition) { switch (condition){ case NORMAL: strategy = new CashNormal(); break; case REBATE: strategy = new CashRebate(0.6); break; case MONEY_RETURN: strategy = new CashReturn(200,50); break; } } public double getResult(double payment){ /** * 根据上面构造器找到的策略,来调用相应的策略解决方法计算结果 */ return strategy.acceptCash(payment); } }
5、定义测试类:
import controller.CashContext; import enum_entity.CashCondition; import org.junit.Test; /** * Created by Administrator on 2017/8/1. */ public class TestCash { @Test public void testCash(){ /** * 传入策略对应的枚举值 */ CashContext context = new CashContext(CashCondition.MONEY_RETURN); /** * 传入消费额 */ double payment = context.getResult(200); System.out.println(payment); } }
至此,代码基本全部写完,由于Java switch分支判断只能传参数是char或者枚举,所以只好实用枚举来实现(作者水平有限)。
刚才说到,策略和简单工厂很像,但区别是策略模式是由策略开关来传入实体对象,而简单工厂模式是根据工厂把对象造出来。