网上购物现在已经是我们生活的常态,在网上购物时商家为了提高商品销量通常会举行一些促销活动,这里模拟促销优惠活动,来展示策略模式的应用
首先创建一个促销策略的接口:
/** * @author xxbb */ public interface PromotionStrategy { /** * 优惠策略 */ void doPromote(); }创建具体的优惠策略,优惠券优惠策略类CouponStrategy、返现促销策略类CashbackStrategy、拼团优惠策略类GroupByStrategy和无优惠策略类EmptyStrategy。
/** * @author xxbb */ public class CouponStrategy implements PromotionStrategy { @Override public void doPromote() { System.out.println("领取优惠券,满100-39"); } } public class CashbackStrategy implements PromotionStrategy{ @Override public void doPromote() { System.out.println("返现促销,满100返现39,次日转回付款账号"); } } public class GroupBuyStrategy implements PromotionStrategy{ @Override public void doPromote() { System.out.println("拼团优惠,满5人成团,享受8折优惠"); } } public class EmptyStrategy implements PromotionStrategy { @Override public void doPromote() { System.out.println("无促销策略"); } }编写促销活动方案类,用于执行策略
public class PromotionActivity { private PromotionStrategy promotionStrategy; public PromotionActivity(PromotionStrategy promotionStrategy){ this.promotionStrategy=promotionStrategy; } public void executor(){ promotionStrategy.doPromote(); } }测试代码:
public class Client { public static void main(String[] args) { PromotionActivity couponActivity=new PromotionActivity(new CouponStrategy()); PromotionActivity cashbackActivity=new PromotionActivity(new CashbackStrategy()); couponActivity.executor(); cashbackActivity.executor(); } }可以看到活动方案类根据传入的策略类的不同执行了不同的策略,这里很好的体现了面向对象的三大特征之一——多态。
然后我们再结合简单工厂模式优化下代码,使用户只需要关系选择的策略,而不需要了解策略的创建过程。
public class PromotionStrategyFactory { interface PromotionKey{ String COUPON="COUPON"; String CASHBACK="CASHBACK"; String GROUP_BUY="GROUP_BUY"; String EMPTY="EMPTY"; } private static Map<String,PromotionStrategy> promotionStrategyMap=new HashMap<>(10); static{ promotionStrategyMap.put(PromotionKey.COUPON,new CouponStrategy()); promotionStrategyMap.put(PromotionKey.CASHBACK,new CashbackStrategy()); promotionStrategyMap.put(PromotionKey.GROUP_BUY,new GroupBuyStrategy()); } private static final PromotionStrategy NON_PROMOTION=new EmptyStrategy(); private PromotionStrategyFactory(){} public static PromotionStrategy getPromotionStrategy(String promotionKey){ PromotionStrategy promotionStrategy=promotionStrategyMap.get(promotionKey); return promotionStrategy==null?NON_PROMOTION:promotionStrategy; } }测试类:
public class Client { public static void main(String[] args) { String promotionKey= "COUPON"; PromotionActivity promotionActivity=new PromotionActivity(PromotionStrategyFactory.getPromotionStrategy(promotionKey)); promotionActivity.executor(); } }在JDK容器中我们有一个常用的比较器——Comparetor接口,其中的compare方法就是策略模式的抽象实现
public interface Comparator<T> { int compare(T o1, T o2); }Comparetor接口下有非常多的实现类。
我们经常会把Comparetor接口作为传入参数实现排序策略,例如Arrays的parallelSort()
public static <T> void parallelSort(T[] a, Comparator<? super T> cmp) { if (cmp == null) cmp = NaturalOrder.INSTANCE; int n = a.length, p, g; if (n <= MIN_ARRAY_SORT_GRAN || (p = ForkJoinPool.getCommonPoolParallelism()) == 1) TimSort.sort(a, 0, n, cmp, null, 0, 0); else new ArraysParallelSortHelpers.FJObject.Sorter<T> (null, a, (T[])Array.newInstance(a.getClass().getComponentType(), n), 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ? MIN_ARRAY_SORT_GRAN : g, cmp).invoke(); }还有TreeMap在实例化时能自定义排序策略
public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; }在Spring源码中的Resource接口也采用策略模式,不同的资源会采用不同的加载策略实现类。
在Spring的初始化时也才采用了策略模式,提供了一个InstantiationStrategy接口,下面提供两种策略实现类SimpleInstantiationStrategy和CglibSubclassingInstantiationStrategy.
策略模式的优点:
符合开闭原则体现多态特性可以避免使用多重条件语句如if,switch来执行具体算法可以提高算法的保密性和安全性策略模式的缺点:
用户必须了解所有的策略,并自行决定使用哪一种策略类当代码中的策略非常多时,代码维护的难度增加委派模式(Delegate Pattern)不属于GoF23种设计模式。委派模式的基本作用就是负责人物的调用和分配,跟代理模式很香,可以看作一种特殊情况下的静态的全权代理,但代理模式注重过程,委派模式注重结果。这里通过老板下达指令,员工执行指令来展示委派模式
public interface IEmployee { void working(String command); } public class EmployeeB implements IEmployee{ @Override public void working(String command) { System.out.println("我是员工B,正在执行"+command+"工作"); } } public class EmployeeA implements IEmployee{ @Override public void working(String command) { System.out.println("我是员工A,正在执行"+command+"工作"); } } public class Leader implements IEmployee{ private Map<String,IEmployee> employeeMap=new HashMap<>(5); public Leader(){ employeeMap.put("登录",new EmployeeA()); employeeMap.put("加密",new EmployeeB()); } /** * 经理委派员工干活 * @param command 命令 */ @Override public void working(String command) { employeeMap.get(command).working(command); } } public class Boss { public void command(String command,Leader leader){ leader.working(command); } } public class TestMain { public static void main(String[] args) { //代理模式注重过程,委派模式注重结果 //策略模式注重可扩展性(外部可扩展性),委派模式注重内部的灵活性和可重复性 //委派模式的核心是分发,调度,派遣,委派模式是静态代理模式和策略模式的一种特殊组合 //分发:Boss将“登录”指令分发给Leader //调度:Leader根据登录指令调度具体的EmployeeA //派遣:EmployeeA被Leader派遣执行working方法 new Boss().command("登录",new Leader()); } }可以看到在Boss处我们将“登录”作为策略分发给Leader,Leader可以看作是Boss的代理,为Boss执行任务。而在Leader中根据Boss给出的策略选择对应的员工执行命令。