• 策略模式


    策略模式

    1.基础知识:

    定义∶

    定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化不会影响到使用算法的用户。

    可以干掉if...else...

    适用场景

    系统有很多类,而他们的区别仅仅在于他们的行为不同

    一个系统需要动态地在几种算法中选择一种

    比如支付方式的选择

    优点

    开闭原则

    避免使用多重条件转移语句

    提高算法的保密性和安全性

    缺点

    客户端必须知道所有的策略类,并自行决定使用哪一个策略类。

    产生很多策略类


    2.实战

    创建学习策略接口

    /**
     * 学习策略
     * @Author LYS
     * @Date 2022/1/16 9:25
     * @Version 1.0
     */
    public interface LearnStrategy {
        void doStudy();
    }
    

    创建不同的学习实现类

    /**
     * 语文学习策略
     * @Author LYS
     * @Date 2022/1/16 9:27
     * @Version 1.0
     */
    public class ChineseLearnStrategy implements LearnStrategy{
        @Override
        public void doStudy() {
            System.out.println("语文学习策略");
        }
    }
    
    /**
     * 空学习策略
     * @Author LYS
     * @Date 2022/1/16 9:28
     * @Version 1.0
     */
    public class EmptyLearnStrategy implements LearnStrategy{
    
        @Override
        public void doStudy() {
            System.out.println("空学习策略");
        }
    }
    
    /**
     * 英语学习策略
     * @Author LYS
     * @Date 2022/1/16 9:27
     * @Version 1.0
     */
    public class EnglishLearnStrategy implements LearnStrategy{
        @Override
        public void doStudy() {
            System.out.println("英语学习策略");
        }
    }
    
    /**
     * 数学学习策略
     * @Author LYS
     * @Date 2022/1/16 9:26
     * @Version 1.0
     */
    public class MathLearnStrategy implements LearnStrategy{
        @Override
        public void doStudy() {
            System.out.println("数学学习策略");
        }
    }
    
    /**
     * 执行策略
     * @Author LYS
     * @Date 2022/1/16 9:33
     * @Version 1.0
     */
    public class LearnActivity {
        private LearnStrategy learnStrategy;
    
        public LearnActivity(LearnStrategy learnStrategy) {
            this.learnStrategy = learnStrategy;
        }
    
        public void executeLearnStrategy(){
            learnStrategy.doStudy();
        }
    }
    

    测试类

    public class Test {
        public static void main(String[] args) {
            LearnActivity learnActivity = null;
            String key = "ENGLISH";
            if("ENGLISH".equals(key)){
                learnActivity = new LearnActivity(new EnglishLearnStrategy());
            }else if("MATH".equals(key)){
                learnActivity = new LearnActivity(new MathLearnStrategy());
            }else if("CHINESE".equals(key)){
                learnActivity = new LearnActivity(new ChineseLearnStrategy());
            }else{
                learnActivity = new LearnActivity(new EmptyLearnStrategy());
            }
            learnActivity.executeLearnStrategy();
        }
    

    控制台输出

    image-20220116103140415

    但是这样的代码编写,还是有ifelse,感觉并没有什么软用,只是比原来逻辑清晰了一点,相当于独立抽离代码块,接下来结合工厂模式和单例模式,打出一套必杀组合拳去掉ifelse。


    创建工厂

    package DesignPattern.strategy;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @Author LYS
     * @Date 2022/1/16 9:29
     * @Version 1.0
     */
    public class LearnStrategyFactory {
        private static Map<String, LearnStrategy> LEARN_STRATEGY_MAP = new HashMap<String, LearnStrategy>();
    
        //类加载的时候就执行了静态代码片,类似饿汉模式,空间换时间   使不同的策略是单例的
        static {
            LEARN_STRATEGY_MAP.put(LearnKey.MATH, new MathLearnStrategy());
            LEARN_STRATEGY_MAP.put(LearnKey.CHINESE, new ChineseLearnStrategy());
            LEARN_STRATEGY_MAP.put(LearnKey.ENGLISH, new EnglishLearnStrategy());
        }
    
        private static final LearnStrategy NON_PROMOTION = new EmptyLearnStrategy();
    
        private LearnStrategyFactory() {
    
        }
    
        public static LearnStrategy getPromotionStrategy(String promotionKey) {
            LearnStrategy promotionStrategy = LEARN_STRATEGY_MAP.get(promotionKey);
            return promotionStrategy == null ? NON_PROMOTION : promotionStrategy;
        }
    
        private interface LearnKey {
            String MATH = "MATH";
            String CHINESE = "CHINESE";
            String ENGLISH = "ENGLISH";
        }
    }
    

    测试类

        public static void main(String[] args) {
    //        String learnKey = "ENGLISH";
    //        String learnKey = "CHINESE";
            String learnKey = "MATH";
            LearnActivity promotionActivity = new LearnActivity(LearnStrategyFactory.getPromotionStrategy(learnKey));
            promotionActivity.executeLearnStrategy();
        }
    

    执行结果:

    image-20220116103454497

    一行代码搞定所有,简介明了,又使用了单例,相比原来一个执行一个策略就new bean的情况,节省了大量空间,简直是艺术!


    3.源码调用:

    观察AbstractAutowireCapableBeanFactory类代码,其使用了懒汉式的方法加载策略,这里是用的时cglib动态代理的加载策略

    也就是使用单例+策略模式

    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
          implements AutowireCapableBeanFactory {
    
       /** Strategy for creating bean instances. */
       private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
       
       	/**
    	 * Set the instantiation strategy to use for creating bean instances.
    	 * Default is CglibSubclassingInstantiationStrategy.
    	 * @see CglibSubclassingInstantiationStrategy
    	 */
    	public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
    		this.instantiationStrategy = instantiationStrategy;
    	}
    

    resource接口策略的抽象
    不同的接口就是对不同策略的实现,比如classpathresource


    comparator.compare比较器,就是对不同的情况有不同策略的实现


    bean的初始化也使用饿了
    image-20220116092224485

  • 相关阅读:
    html5跨域通讯之postMessage的用法
    zTree插件之多选下拉菜单代码
    css3创建一个上下线性渐变色背景的div
    zTree插件之单选下拉菜单代码
    PhoneGap中navigator.notification.confirm的用法详解
    CCS3属性之text-overflow:ellipsis;的用法和注意之处
    HTML5的自定义属性data-* 的用法解析
    HSSFWorkbook转MultipartFile InputStream转MultipartFile
    @Transactional
    synchronized volatile
  • 原文地址:https://www.cnblogs.com/yslu/p/15808953.html
Copyright © 2020-2023  润新知