zoukankan      html  css  js  c++  java
  • 设计模式之策略模式实战

    本文原文链接地址:http://nullpointer.pw/design-patterns-strategy.html
    类型:行为型模式

    意图:定义一系列算法,不同算法策略可以相互替换,并且互不影响。

    主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

    使用场景:一个系统需要动态地在几种算法中选择一种。

    设计模式系列文章目录

    角色

    • 策略上下文角色:持有抽象策略角色的引用,访问策略的入口
    • 抽象策略角色
    • 具体策略角色

    UML

    实战

    以抽奖活动发奖为例,奖品多种多样,可能是现金奖,话费奖品,实物奖等等,每种奖品的发放方式都不一样,比如现金是直接转账,话费奖品是调用运营商提供接口发放,实物奖需要人工快递寄送。在未采用策略模式之前,少不了使用 if...else...来判断发放,当增加一种奖品类型时,就需要增加 if 判断。而采取策略模式之后,只需实现一个策略类即可,对原来的逻辑无需做任何改动,也不会影响其他策略的正常逻辑。

    本文示例UML图

    定义抽象策略接口

    /**
     * @author WeJan
     * @since 2020-02-06
     */
    public interface PrizeSendStrategy {
        String DEFAULT = "default";
        String MONEY = "money";
        String IN_KIND = "in_kind";
        String CALL_CHARGE = "call_charge";
    
        String type();
    
        void doSend();
    }
    

    实现具体的策略

    @Component
    public class CallChargePrizeSendStrategy implements PrizeSendStrategy {
        @Override
        public String type() {
            return CALL_CHARGE;
        }
    
        @Override
        public void doSend() {
            System.out.println("发放话费奖品");
        }
    }
    
    @Component
    public class MoneyPrizeSendStrategy implements PrizeSendStrategy {
        @Override
        public String type() {
            return MONEY;
        }
    
        @Override
        public void doSend() {
            System.out.println("发放现金奖品");
        }
    }
    
    @Component
    public class InKindPrizeSendStrategy implements PrizeSendStrategy {
        @Override
        public String type() {
            return IN_KIND;
        }
    
        @Override
        public void doSend() {
            System.out.println("发放实物奖品");
        }
    }
    
    @Component
    public class EmptyPrizeSendStrategy implements PrizeSendStrategy {
        @Override
        public String type() {
            return DEFAULT;
        }
    
        @Override
        public void doSend() {
            System.out.println("不发奖");
        }
    }
    

    实现对抽象策略封装的上下文对象

    /**
     * @author WeJan
     * @since 2020-02-06
     */
    public class PrizeSendContext {
        private PrizeSendStrategy prizeSendStrategy;
        public PrizeSendContext() {
        }
    
        public void setPrizeSendStrategy(PrizeSendStrategy prizeSendStrategy) {
            this.prizeSendStrategy = prizeSendStrategy;
        }
    
        public void executePrizeSendStrategy() {
            prizeSendStrategy.doSend();
        }
    }
    

    抽取策略工厂

    客户端需要判断要使用哪一个具体的策略类,若还是按照传统的方法 if...else...来判断策略模式就没有意义了,因此策略模式一般都是结合其他模式共同使用。本文中策略类使用 String 来标识,也可以在策略类中增加抽象方法,返回值为枚举类型。

    @Component
    public class PrizeSendStrategyFactory implements ApplicationContextAware {
        private static final Map<String, PrizeSendStrategy> PRIZE_SEND_STRATEGY_MAP = new HashMap<>();
    
        public static PrizeSendStrategy getPrizeSendStrategy(String strategyKey) {
            return PRIZE_SEND_STRATEGY_MAP.getOrDefault(strategyKey, PRIZE_SEND_STRATEGY_MAP.get(DEFAULT));
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            Map<String, PrizeSendStrategy> beans = applicationContext.getBeansOfType(PrizeSendStrategy.class);
            beans.values().forEach(bean -> PRIZE_SEND_STRATEGY_MAP.put(bean.type(), bean));
        }
    }
    

    测试

    /**
     * @author WeJan
     * @since 2020-02-06
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = App.class)
    public class StrategyTest {
    
        @Test
        public void test() {
            PrizeSendContext sendContext = new PrizeSendContext();
            sendContext.setPrizeSendStrategy(PrizeSendStrategyFactory.getPrizeSendStrategy("money"));
            sendContext.executePrizeSendStrategy();
        }
    
    }
    

    输出结果为:

    发放现金奖品
    

    示例代码

    参考

  • 相关阅读:
    二分法模板
    二分答案模板
    51nod 1010 只包含因子2 3 5的数
    三次握手和四次挥手(面试必问)
    TCP协议和UDP协议
    纯CSS3画出小黄人并实现动画效果
    正则表达式里字符串”不包含”匹配技巧
    12个C语言面试题,涉及指针、进程、运算、结构体、函数、内存,看看你能做出几个!
    使用jTopo给Html5 Canva中绘制的元素添加鼠标事件_html5教程技巧
    程序猿们,快用Emoji表情写代码吧
  • 原文地址:https://www.cnblogs.com/vcmq/p/12542367.html
Copyright © 2011-2022 走看看