在实际开发中,可能会遇到这样一个情况,某一功能的实现分为多种算法,这些算法可以认定为策略,在实际操作时选择不同算法或策略进行操作得出最终结果。在实际生活中,这些例子也是举不胜举,例如,商场举行活动,满100元减10元,满200元减30元,满500元减100元等等...这样每消费一笔,根据这一笔钱消费的多少,计算最终应支付的钱对应着不同的算法,这些对应的不同计算方法就可以认定为是不同的策略。在某东购物时,根据不同的用户等级,打折力度也是不同的。
策略模式的UML类图参照下图:
假如没有策略模式,实现某东购物计算最终付款的方法怎样呢?
package com.strategy.demo; public class NoStrategy { /** * 不使用测量模式实现 * @param args */ private static final int NOCARDUSER=1; private static final int IRONCARDUSER=2; private static final int GOLDCARDUSER=3; public static void main(String[] args) { NoStrategy NoStrategy1=new NoStrategy(); NoStrategy NoStrategy2=new NoStrategy(); NoStrategy NoStrategy3=new NoStrategy(); System.out.println("没有卡牌的买家买100元货物最终应付款:"+NoStrategy1.getPrice(100.0, 1)); System.out.println("铁牌的买家买100元货物最终应付款:"+NoStrategy2.getPrice(100.0, 2)); System.out.println("金牌的买家买100元货物最终应付款:"+NoStrategy3.getPrice(100.0, 3)); } private double getNoCardPrice(double price){ return price; } private double getIronCardPrice(double price){ return price*0.9; } private double getGoldCardPrice(double price){ return price*0.7; } private double getPrice(double price,int type){ if(type==NOCARDUSER){ return getNoCardPrice(price); }else if(type ==IRONCARDUSER){ return getIronCardPrice(price); }else if(type ==GOLDCARDUSER){ return getGoldCardPrice(price); }else { return 0; } } }
运行实例:
呀,得出正确的答案了,这时你是不是应该满足了呢,应该高枕无忧了呢?突然,主管说要增加钻石用户的类别,钻石用户打六折,这时你怎么实现呢?在里面在增加钻石用户的类型,再增加计算钻石用户的方法,再再最后的判断里增加i f else? 这样的确可以实现功能,但是是不是不满足开闭原则呢?而且随着用户种类的不断增加,你的if else是不是也越来越长,逻辑也越来越复杂呢?导致系统扩展性和稳定性越来越差呢? 所以,这种方式在实际中显然实不可取的,下面我们看一下如何使用策略模式来实现上面的需求。
1.PriceStrategyInterface 接口,对应UML类图中的Strategy接口:
package com.strategy.demo; public interface PriceStrategyInterface { double calPrice(double price); }
2.实现类,无卡用户:
package com.strategy.demo; public class NoCardUserStrategy implements PriceStrategyInterface { /** * 无牌买家,原价 */ @Override public double calPrice(double price) { return price; } }
3.实现类,铁卡用户:
package com.strategy.demo; public class IronCardUserStrategy implements PriceStrategyInterface { /* * 铁牌买家 * (non-Javadoc) * @see com.strategy.demo.PriceStrategyInterface#calPrice(double) */ @Override public double calPrice(double price) { return price*0.9; } }
4.实现类,金卡用户:
package com.strategy.demo; public class GoldCardUserStrategy implements PriceStrategyInterface { /** * 金牌买家 */ @Override public double calPrice(double price) { return price*0.7; } }
5.环境对象,用来操作策略:
package com.strategy.demo; public class PriceContext { /** * 操作类 */ PriceStrategyInterface priceStrategyInterface; /* * 通过初始化传入对象 */ public PriceContext(PriceStrategyInterface priceStrategyInterface) { this.priceStrategyInterface=priceStrategyInterface; } /* * 通过对象计算返回值 */ public double getPrice(double price){ return priceStrategyInterface.calPrice(price); } }
环境对象初始化时,将对应的策略对象传入,然后调用方法返回计算值。
6.构建测试类,测试:
package com.strategy.demo; public class TestClass { public static void main(String[] args) { PriceContext priceContext=new PriceContext(new NoCardUserStrategy()); System.out.println("没有卡牌的买家买100元货物最终应付款:"+priceContext.getPrice(100.0)); PriceContext priceContext2=new PriceContext(new IronCardUserStrategy()); System.out.println("铁牌的买家买100元货物最终应付款:"+priceContext2.getPrice(100.0)); PriceContext priceContext3=new PriceContext(new GoldCardUserStrategy()); System.out.println("金牌的买家买100元货物最终应付款:"+priceContext3.getPrice(100.0)); } }
运行上面的实例:
得到了和第一个方法一样的正确答案,这时我们假如要增加一个钻石买家的种类,怎么实现呢?我们只需要增加一个策略实现类:
package com.strategy.demo; public class DiamondUserStrategy implements PriceStrategyInterface { @Override public double calPrice(double price) { return price*0.6; } }
然后测试类增加一条钻石类买家的购物:
package com.strategy.demo; public class TestClass { public static void main(String[] args) { PriceContext priceContext=new PriceContext(new NoCardUserStrategy()); System.out.println("没有卡牌的买家买100元货物最终应付款:"+priceContext.getPrice(100.0)); PriceContext priceContext2=new PriceContext(new IronCardUserStrategy()); System.out.println("铁牌的买家买100元货物最终应付款:"+priceContext2.getPrice(100.0)); PriceContext priceContext3=new PriceContext(new GoldCardUserStrategy()); System.out.println("金牌的买家买100元货物最终应付款:"+priceContext3.getPrice(100.0)); PriceContext priceContext4=new PriceContext(new DiamondUserStrategy()); System.out.println("钻石卡的买家买100元货物最终应付款:"+priceContext4.getPrice(100.0)); } }
运行实例:
是不是扩展起来特别容易?条理也十分清晰。总结一下策略模式的优点:
1. 结构清晰,使用简单直观;
2. 系统耦合性降低,扩展方便;
3. 操作封装彻底,数据更为安全。(在TestClass中,只知道相关实现类,并不涉及具体计算方法)
当然,策略方式也存在一定的缺点:
由图可以直观的看出,随着策略的不断增加,子类数量变得庞大。
喜欢的朋友关注我和我的微信平台