策略模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
下面将以商场打折为例子,说明策略模式。商场收银如何促销,用打折还是返利其实都是一些算法,用简单工厂来生产算法对象,这没有错,但算法本身只是一种策略,最重要的是这些算法是随时都可能互相替换的,这就是变化点,而封装变化点是我们面向对象的一种很重要的思维方式。
1.Strategy类,定义所有支持的算法的公共接口:
1 package com.lujie; 2 //抽象算法类 3 public interface CashSuper { 4 //算法方法 5 public abstract double acceptCash(double money); 6 }
2.ConcreteStrategy,封装了具体的算法或行为,继承与strategy
package com.lujie; //打折收费子类 public class CashRebate implements CashSuper{ private double moneyRebate=1d; public void setMoneyRebat(double moneyRebat) { this.moneyRebate = moneyRebat; } public double getMoneyRebat() { return moneyRebate; } @Override public double acceptCash(double money) { return money*moneyRebate; } public CashRebate(String moneyRebate) { // TODO Auto-generated constructor stub this.moneyRebate=Double.valueOf(moneyRebate).doubleValue(); } }
1 package com.lujie; 2 3 4 //返利收费子类 5 public class CashReturn implements CashSuper{ 6 7 private double moneyCondition=0.0d; 8 private double moneyReturn=0.0d; 9 public void setMoneyCondition(double moneyCondition) { 10 this.moneyCondition = moneyCondition; 11 } 12 public void setMoneyReturn(double moneyReturn) { 13 this.moneyReturn = moneyReturn; 14 } 15 public double getMoneyCondition() { 16 return moneyCondition; 17 } 18 public double getMoneyReturn() { 19 return moneyReturn; 20 } 21 public CashReturn(String moneyCondition,String moneyReturn) { 22 // TODO Auto-generated constructor stub 23 this.moneyCondition=Double.valueOf(moneyCondition).doubleValue(); 24 this.moneyReturn=Double.valueOf(moneyReturn).doubleValue(); 25 } 26 @Override 27 public double acceptCash(double money) { 28 // TODO Auto-generated method stub 29 double result=money; 30 if(money>=moneyCondition) 31 result=money-Math.floor(money/moneyCondition)*moneyReturn; 32 return result; 33 } 34 }
1 package com.lujie; 2 //正常收费子类 3 public class CashNormal implements CashSuper{ 4 @Override 5 public double acceptCash(double money) { 6 // TODO Auto-generated method stub 7 return money; 8 } 9 }
3.Context,用一个ContreteStrategy来配置,维护一个对strategy对象的引用。
1 package com.lujie; 2 //策略模式 3 public class CashContext { 4 private CashSuper cs;//声明一个CashSuper对象 5 public CashContext(String type) {//注意参数不是具体的收费策略对象, 6 //而是一个字符串,表示收费类型 7 //初始化时,传入具体的策略对象 8 switch (type) { 9 case "正常收费": 10 CashNormal cs0=new CashNormal();//根据具体的策略对象,调用器算法的方法 11 cs=cs0; 12 break; 13 case "满300返100": 14 CashReturn cs1=new CashReturn("300","100"); 15 cs=cs1; 16 break; 17 case "打8折": 18 CashRebate cs2=new CashRebate("0.8"); 19 cs=cs2; 20 break; 21 //将实例化具体策略的过程由客户端转移到Context类中,简单工厂的应用 22 } 23 } 24 public double getResult(double money) { 25 return cs.acceptCash(money); 26 } 27 }
4.测试用例:
1 package com.lujie; 2 3 public class testStrategyMethod { 4 5 public static void main(String[] args) { 6 testStrategyMethod test=new testStrategyMethod(); 7 test.getResult("正常收费"); 8 test.getResult("满300返100"); 9 test.getResult("打8折"); 10 } 11 public void getResult(String type) { 12 double total=0.0d; 13 // TODO Auto-generated method stub 14 CashContext csSuper=new CashContext(type); 15 double totalPrices=0d; 16 totalPrices=csSuper.getResult(3000); 17 total=total+totalPrices; 18 System.out.println(type+"为:"+total); 19 } 20 21 }
5.测试结果: