• 策略模式+工厂模式+模板模式彻底取代 if...else...


    在平时开发中,有时避免不了使用大量判断,简单处理的话就使用if...else...了,但过多层的if else对于性能有很大的开销,而且业务复杂的话,耦合太重,对于后期的拓展也不是很友好,所以使用策略模式。

    1. 策略+工厂实现相同业务抽象

    策略模式:一种解耦的方法,它对算法进行封装,使得算法的调用和算法本身分离。使用策略模式客户端代码不需要调整,算法之间可以互相替换,因为不同的算法实现的是同一个接口。策略模式是一种对象行为型模式。策略模式符合“开闭原则”。

    策略模式包括如下角色:

    • Context :环境类

    • Strategy:抽象策略类

    • ConcreteStrategy:具体策略类

    下面简单抽象下业务逻辑:

    String name = "shaqiang";
    
    if(name.equals("saobin")){
        System.out.println("I am SaoBin");
    }else if(name.equals("shaqiang")){
        System.out.println("I am ShaQiang");
    }else if(name.equals("weifeng")){
        System.out.println("I am WeiFeng");
    }

    有成员“骚斌”、“傻强”、“伟峰”···,其执行逻辑基本一样,基于策略模式对其进行改造:

    1.1 定义策略接口

    将成员的业务方法抽象为统一的策略接口。其中 InitializingBean 接口来自Spring框架,用于实现环境的统一工厂。

    import org.springframework.beans.factory.InitializingBean;
    
    /**
     * 策略总接口*/
    public interface NameHandler extends InitializingBean {
        /**
         * 输出名称
         * @param name
         */
        public void myName(String name);
    
    }

    1.2 实现策略工厂

    此处的工厂即策略模式下的 “环境类” 要素,功能为根据不同的name找到其对应的不同的策略实现,实现方法为将实现NameHandler接口的类都装载到strategyMap里,除使用工厂实现外,也可以使用枚举+代理实现。

    import org.springframework.util.StringUtils;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 工厂设计模式*/
    public class NameSetFactory {
    
        private static Map<String, NameHandler> strategyMap = new HashMap<>();
    
        /**
         * 根据name获取对应的handler实现
         * @param name
         * @return
         */
        public static NameHandler getInvokeStrategyMap(String name){
            return strategyMap.get(name);
        }
    
        /**
         * 注册
         * @param name
         * @param handler
         */
        public static void register(String name, NameHandler handler){
            if(StringUtils.isEmpty(name)||null == handler){
                return;
            }
            strategyMap.put(name,handler);
        }
    }

    1.3 为各成员实现各自的具体策略实现类

    将各自实现类声明为组件(用于维护工厂),org.springframework.beans.factory.InitializingBean#afterPropertiesSet内部实现工厂注册。

    import org.springframework.stereotype.Component;
    
    /**
     * saobin策略实现*/
    @Component
    public class SaoBinHandler implements NameHandler {
    
        /**
         * 输出名称
         * @param name
         */
        @Override
        public void myName(String name) {
            System.out.println("I am SaoBin");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            NameSetFactory.register("saobin",this);
        }
    }
    import org.springframework.stereotype.Component;
    
    /**
     * shaqiang策略实现*/
    @Component
    public class ShaQiangHandler implements NameHandler {
    
        /**
         * 输出名称
         * @param name
         */
        @Override
        public void myName(String name) {
            System.out.println("I am ShaQiang");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            NameSetFactory.register("shaqiang",this);
        }
    }
    import org.springframework.stereotype.Component;
    
    /**
     * weifeng策略实现*/
    @Component
    public class WeiFengHandler implements NameHandler {
    
        /**
         * 输出名称
         * @param name
         */
        @Override
        public void myName(String name) {
            System.out.println("I am WeiFeng");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
            NameSetFactory.register("weifeng",this);
        }
    }

    1.4 新增if逻辑拓展

     如上,如果后续再加新成员的业务,只需要实现其对应的具体策略类即可,不需要关注其对其他成员的业务是否有影响。

    2. 策略模式+工厂模式+模板模式实现不同业务

    现在来了新需求,之前成员实现的方法基本一致,但现在要求:“骚斌”实现打印名称,“傻强”实现跳舞,“伟峰”实现打印名称和跳舞,后续随时会有新增成员和新增功能,基于上面的实现,可以在策略总接口中新增跳舞方法,实现如下:

     

     可以看出,在总策略接口中新增“跳舞”方法后,没有该功能的“骚斌”也需要实现它,这个就很不友好了。下面对其进行改造:

    2.1 模板设计模式改造总策略接口

    将原先的接口改造为抽象类,实现模板模式,所有的功能在类中定义,子类要实现具体功能,重写即可。

    import org.springframework.beans.factory.InitializingBean;
    
    /**
     * 策略抽象类(模板)
     */
    public abstract class AbstractNameHandler implements InitializingBean {
        /**
         * 输出名称
         * @param name
         */
         public void myName(String name){
             throw new UnsupportedOperationException();
         };
    
        /**
         * 跳舞
         * @param name
         */
        public void dance(String name){
            throw new UnsupportedOperationException();
        };
    
    }

    2.2 策略实现

    各成员只需实现其对应的策略方法即可。

    如下,测试成员功能,对于有具体实现的方法,成员会执行,如果没有具体实现,会抛出异常。

     经过上面改造,后面如果新增成员或者新功能实现,新增策略实现即可。这种改造符合开闭原则,适用较为复杂的逻辑判断。

  • 相关阅读:
    adb命令使用总结
    python os.system()和os.popen()
    Source Insight 中文注释为乱码解决办法(完美解决,一键搞定)
    Source Insight 常用设置
    Source Insight 有用设置配置
    Source Insight 常用设置和快捷键大全
    Source Insight 4.0常用设置
    远程桌面中Tab键不能补全的解决办法
    python中if __name__ == '__main__': 的解析
    python os用法笔记
  • 原文地址:https://www.cnblogs.com/zjfjava/p/13450035.html
Copyright © 2020-2023  润新知