本文共 4511 字,大约阅读时间需要 15 分钟。
策略模式(strategy),它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式算法的替换不会影响到使用算法的客户。
在有多种算法相似的情况下,使用 if...else 或 switch...case 所带来的复杂性和臃肿性。
该程序主要通过模拟商场收费打折的功能实现。
1、创建现金收费抽象类
public abstract class CashSuper { public abstract double acceptCash(double money);}
2、创建各种收费的具体实现
2.1 正常收费
public class CashNormal extends CashSuper { @Override public double acceptCash(double money) { return money; }}
2.2 返利收费 满300送100
public class CashReturn extends CashSuper { private double moneyCondition; private double moneyReturn; public CashReturn(double moneyCondition, double moneyReturn) { this.moneyCondition = moneyCondition; this.moneyReturn = moneyReturn; } @Override public double acceptCash(double money) { double result = 0d; if(money > moneyCondition){ result = money - Math.floor(money/moneyCondition) * moneyReturn; } return result; }}
2.3 打折收费
public class CashRebate extends CashSuper { private double rebateRate = 1d; public CashRebate(double rebateRate) { this.rebateRate = rebateRate; } @Override public double acceptCash(double money) { return money*rebateRate; }}
3、context上下文,维护一个对Strategy对象的引用
public class Context { private CashSuper cashSuper; public Context(CashSuper cashSuper) { this.cashSuper = cashSuper; } public double getMoney(double money){ return cashSuper.acceptCash(money); }}
4、策略模式测试
//策略模式应用 Context context = null; String type = "normal"; switch (type){ case "normal": context = new Context(new CashNormal()); break; case "return": context = new Context(new CashReturn(300,100)); break; case "rebate": context = new Context(new CashRebate(0.8)); break; } double total = context.getMoney(2000); System.out.println(total);
至此,策略模式的解释已经结束,可以看出以上代码的优缺点:
优点:1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性好。
缺点:1、客户端必须知道所有的策略类,并自己决定由那个策略类。 2、策略类会很多。
解决这个缺点方法:策略+简单工厂
5、策略模式+简单工厂结合
策略模式需要在客户端判断用哪个算法,那么为了解决这个问题就可以将策略模式和简单工厂结合起来。具体的方法就是 简单工厂与策略模式中的Context类结合
改进的Context代码:
public class SimpleFactoryContext { CashSuper cashSuper = null; public SimpleFactoryContext(String type){ switch (type){ case "normal": cashSuper = new CashNormal(); break; case "return": cashSuper = new CashReturn(300,100); break; case "rebate": cashSuper = new CashRebate(0.8); break; } } public double getResult(double money){ return cashSuper.acceptCash(money); }}
优点:解决了需要在客户端判断使用那个实现的缺点;
缺点:在cashContext中用到了swith,也就是说,如果我们需要增加一种算法,比如"满200减50",就必须更改cashContext中的switch代码。
6、策略模式+简单工厂+反射机制
策略模式需要在客户端判断用哪个算法,那么为了解决这个问题就可以将策略模式和简单工厂结合起来。具体的方法就是 简单工厂与策略模式中的Context类结合
改进的Context代码:
public class FsContext { private static final String[] CUSH_CLASS_NAME = { "com.zbf.strategyMode.CashNormal", "com.zbf.strategyMode.CashRebate", "com.zbf.strategyMode.CashReturn" }; CashSuper cashSuper = null; public FsContext(int type,Class[] paramsType, Object[] params){ try { Class clazz=Class.forName(CUSH_CLASS_NAME[type]); Constructor constructor=clazz.getConstructor(paramsType); this.cashSuper=(CashSuper)constructor.newInstance(params); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public double getResult(double money){ return cashSuper.acceptCash(money); }}
7、测试
/** * 策略模式与简单工厂模式的结合,使得客户端只需知道sfc类即可,而单纯的策略模式客户端需要认识context及caseSuper, * 此方式降低了耦合度 */ SimpleFactoryContext sfc = new SimpleFactoryContext("return"); double m = sfc.getResult(2000); System.out.println(m); //反射机制 Class[] paramTypes2 = {double.class}; Object[] params2 = {0.8d}; FsContext fc = new FsContext(1,paramTypes2,params2); double mon = fc.getResult(2000); System.out.println(mon);
注:参考文献《大话设计模式》程杰著。
转载地址:http://oklii.baihongyu.com/