• 案例突破——再探策略模式


    一、背景介绍

    在做项目重构的过程中,发现对于主题讨论中,针对于学生评论/回复的内容的按照评论/回复日期排序、按照评论数量排序、按照点赞次数排序可以使用策略模式进行优化。

    二、 思路方案

    1. 策略模式基本概念
    2. 策略模式类图
    3. 策略模式基本代码
    4. 策略模式还可以进行优化的地方
    5. 对策略模式进行优化

    三、过程

    1. 策略模式基本概念

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

    2. 策略模式类图

    在这里插入图片描述

    3. 策略模式基本代码

    策略类

    package com.wangwei.strategypattern.normal;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : ConcreteStrategy
     * @description : [描述说明该类的功能]
     * @createTime : [2023/9/7 10:34]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:34]
     * @updateRemark : [描述说明本次修改内容]
     */
    public class ConcreteStrategyA implements IStrategy{
        public void AlgorithmInterface(){
            System.out.println("算法A实现");
        }
    }
    
    package com.wangwei.strategypattern.normal;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : ConcreteStrategy
     * @description : [描述说明该类的功能]
     * @createTime : [2023/9/7 10:34]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:34]
     * @updateRemark : [描述说明本次修改内容]
     */
    public class ConcreteStrategyB implements IStrategy{
        public void AlgorithmInterface(){
            System.out.println("算法B实现");
        }
    }
    
    package com.wangwei.strategypattern.normal;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : ConcreteStrategy
     * @description : [描述说明该类的功能]
     * @createTime : [2023/9/7 10:34]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:34]
     * @updateRemark : [描述说明本次修改内容]
     */
    public class ConcreteStrategyC implements IStrategy{
        public void AlgorithmInterface(){
            System.out.println("算法C实现");
        }
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    抽象策略类

    package com.wangwei.strategypattern.normal;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : IStrategy
     * @description : [描述说明该类的功能]
     * @createTime : [2023/9/7 10:37]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:37]
     * @updateRemark : [描述说明本次修改内容]
     */
    public interface IStrategy {
        void AlgorithmInterface();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Context类

    package com.wangwei.strategypattern.normal;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : Context
     * @description : [公共上下文]
     * @createTime : [2023/9/7 10:38]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:38]
     * @updateRemark : [描述说明本次修改内容]
     */
    public class Context {
        IStrategy iStrategy=null;
    
        public Context(IStrategy iStrategy) {
            this.iStrategy = iStrategy;
        }
    
        public void ContextInterface(){
            iStrategy.AlgorithmInterface();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    客户端

    package com.wangwei.strategypattern.normal;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : Client
     * @description : [描述说明该类的功能]
     * @createTime : [2023/9/7 10:40]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:40]
     * @updateRemark : [描述说明本次修改内容]
     */
    public class Client {
        public static void main(String[] args) {
            Context context=null;
    
            context= new Context(new ConcreteStrategyA());
            context.ContextInterface();
    
            context = new Context(new ConcreteStrategyB());
            context.ContextInterface();
    
            context = new Context(new ConcreteStrategyB());
            context.ContextInterface();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    4. 策略模式还可以进行优化的地方

    当我们需要增加新的策略的时候,是需要修改客户端的代码,那么对于客户端来说是不符合开闭原则的。

    5. 对策略模式的优化(配置文件+反射)

    package com.wangwei.strategypattern.better;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : ConcreteStrategy
     * @description : [描述说明该类的功能]
     * @createTime : [2023/9/7 10:34]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:34]
     * @updateRemark : [描述说明本次修改内容]
     */
    public class ConcreteStrategyA implements IStrategy {
        public void AlgorithmInterface(){
            System.out.println("算法A实现");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    package com.wangwei.strategypattern.better;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : ConcreteStrategy
     * @description : [描述说明该类的功能]
     * @createTime : [2023/9/7 10:34]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:34]
     * @updateRemark : [描述说明本次修改内容]
     */
    public class ConcreteStrategyB implements IStrategy {
        public void AlgorithmInterface(){
            System.out.println("算法B实现");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    package com.wangwei.strategypattern.better;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : ConcreteStrategy
     * @description : [描述说明该类的功能]
     * @createTime : [2023/9/7 10:34]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:34]
     * @updateRemark : [描述说明本次修改内容]
     */
    public class ConcreteStrategyC implements IStrategy {
        public void AlgorithmInterface(){
            System.out.println("算法C实现");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    package com.wangwei.strategypattern.better;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.InvocationTargetException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : Context
     * @description : [公共上下文]
     * @createTime : [2023/9/7 10:38]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:38]
     * @updateRemark : [描述说明本次修改内容]
     */
    public class Context {
    
        static Map<String,String> config = new HashMap<>();
        static Map<String,IStrategy> configBean = new HashMap<>();
        //提前读取配置文件中的策略,并提前准备好已有的策略对象
        static {
            InputStream inputStream = Context.class.getResourceAsStream("/config.properties");
            Properties properties = new Properties();
            try {
                properties.load(inputStream);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            String strategyType = properties.getProperty("strategyType");
            String[] strs = strategyType.split(",");
    
            for (String string : strs) {
                String key = string.split(":")[0];
                String value = string.split(":")[1];
                // 去掉头部空格
                String key1 = key.trim();
                String value1 = value.trim();
                config.put(key1, value1);
            }
            //提前准备好已有的策略对象
            for (Map.Entry<String,String> entry:config.entrySet()) {
                Class strategyClass ;
                try {
                    strategyClass = Class.forName(entry.getValue());
                    configBean.put(entry.getKey(),(IStrategy) strategyClass.getConstructor().newInstance());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
    
            }
    
        }
        IStrategy iStrategy;
        public Context(String type) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
            if(configBean.containsKey(type)){
                this.iStrategy = configBean.get(type);
            }else {
                Class strategyClass = Class.forName(config.get(type));
                this.iStrategy = (IStrategy)strategyClass.getConstructor().newInstance();
            }
        }
        public void ContextInterface(){
            iStrategy.AlgorithmInterface();
        }
    
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    package com.wangwei.strategypattern.better;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : IStrategy
     * @description : [描述说明该类的功能]
     * @createTime : [2023/9/7 10:37]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:37]
     * @updateRemark : [描述说明本次修改内容]
     */
    public interface IStrategy {
        void AlgorithmInterface();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    package com.wangwei.strategypattern.better;
    
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    
    /**
     * @author : [WangWei]
     * @version : [v1.0]
     * @className : Client
     * @description : [描述说明该类的功能]
     * @createTime : [2023/9/7 10:40]
     * @updateUser : [WangWei]
     * @updateTime : [2023/9/7 10:40]
     * @updateRemark : [描述说明本次修改内容]
     */
    public class Client {
        public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException {
            /*
            1.前端通过下拉框选择不同的类型
            2.类型是从配置文件中读取的
             */
            Context context;
            context= new Context("strategyA");
            context.ContextInterface();
    
            context = new Context("strategyB");
            context.ContextInterface();
    
            context = new Context("strategyC");
            context.ContextInterface();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    四、总结

    1. 优点:配置文件+反射的方式,符合开闭原则。用户可以在不修改原有代码的基础上选择算法,也可以灵活的增加新的算法。

    2. 缺点:无法同时在客户端使用多个策略类。

    3. 关键点:都是对通一份数据,根据不同的算法进行处理。

    4. 什么时候使用策略模式:一个系统需要动态地在几种算法中选择一种。

    五、升华

    1. 学习是一个反复的过程:通过项目切实的需求来结合具体的设计模式,在反过来在此基础上优化设计模式。
  • 相关阅读:
    Safe Head机制技术理论分析
    Docker mongoDB容器备份与恢复
    痞子衡嵌入式:借助i.MXRT10xx系列INIT_VTOR功能可以缩短程序热重启时间
    【DDIM】DENOISING DIFFUSION IMPLICIT MODELS【论文精读】【视频讲解】【公式推导】
    程序员不得不知道的 API 接口常识
    Java完全自学手册,从外包到大厂,再到年薪100万都靠它
    UE4基础篇十三:物理
    MySQL增删改查【进阶篇】万字图文超详细讲解
    话题浏览上涨70.6%!搞到“新顶流”了,小红书数据洞察品牌动作!
    输入/输出应用程序接口和设备驱动程序接口
  • 原文地址:https://blog.csdn.net/wangwei021933/article/details/133441042