gof23——策略模式

    技术2025-08-21  20

    gof23——策略模式

    一、策略模式的使用场景二、策略模式的应用场景三、策略模式在源码中的体现四、策略模式的优缺点五、委派模式 策略模式(Strategy Pattern)是指定义了算法家族并分别封装恰里,让它们之间可以相互替换,此模式使得算法的变化不会影响使用算法的用户

    一、策略模式的使用场景

    系统中有很多类,而他们的区别仅仅在于行为的不同一个系统需要动态地再几种算法中选择一种

    二、策略模式的应用场景

    网上购物现在已经是我们生活的常态,在网上购物时商家为了提高商品销量通常会举行一些促销活动,这里模拟促销优惠活动,来展示策略模式的应用

    首先创建一个促销策略的接口:

    /** * @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给出的策略选择对应的员工执行命令。

    Processed: 0.014, SQL: 9