• 让代码变美的第二天 - 策略模式


    丑陋的模样

        public Fruit buyFruit(String name) {
            if ("苹果".equals(name)) {
                return new BuyApple().buy();
            } else if ("香蕉".equals(name)) {
                return new BuyBanana().buy();
            } else if ("西瓜".equals(name)) {
                // 买西瓜
                if (true) {
                    // todo
                } else {
                    // todo
                }
            }
            return null;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 分支判断越来越多,方法就会越来越大,就算每个分支压缩到一个function,当超过一定数量也会很难看。最重要的是破坏了设计的开闭原则。

    变美步骤

    第一步 - 基本预期

    思考:这个功能,这个方法改动到底是不是很频繁,新增的判断逻辑(if else)将来会不会很频繁。有个预期就行,如果没有预期,那就看实际改动次数。

    • 如果不频繁,建议就这样吧,只要结构清晰,方便review代码就行。不鼓励过度设计,毕竟开发时间都是有限的。
    • 如果很频繁,就看第二步

    第二步 - 梳理核心逻辑

    判断当前功能是不是都是由一个策略值,来决定后面整体流程,并且每个流程都不太相同,这样容易想到可以使用策略模式来进行优化。
    如果当前功能不光有不同策略处理流程,还有共同的处理流程,那么可以把不同策略处理流程抽取出来,使用策略模式进行优化,共同的部分不在本文讨论范围内。

    第三步 - 重构

    只讨论使用spring项目
    给策略进行定义,比如水果场景

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface FruitScene {
        String value();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    给所有策略对应的处理流抽象成一个方法,取个名字,比如买水果

    public interface BuyFruit {
        Fruit buy();
    }
    
    • 1
    • 2
    • 3

    定义每个策略对应处理流程,比如买苹果、买香蕉

    @Component
    @FruitScene("苹果")
    public class BuyApple implements BuyFruit {
        @Override
        public Fruit buy() {
            System.out.println("买苹果");
            return new Fruit("苹果");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    @Component
    @FruitScene("香蕉")
    public class BuyBanana implements BuyFruit {
        @Override
        public Fruit buy() {
            System.out.println("买香蕉");
            return new Fruit("香蕉");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 将来新增处理流程只需要新增一个类、方法

    把定义的策略场景和处理流程进行关联

    @Component
    public class BuyFruitFactory {
        private static Map<String, BuyFruit> getBuyFruitMap = new HashMap<>();
    
        @Autowired
        private void setBuyFruitMap(List<BuyFruit> buyFruitList) {
            buyFruitList.forEach(fs -> {
                FruitScene fruitScene = fs.getClass().getAnnotation(FruitScene.class);
                if (fruitScene != null) {
                    getBuyFruitMap.put(fruitScene.value(), fs);
                }
            });
        }
    
        public static Fruit buy(String fruitName) {
            return getBuyFruitMap.get(fruitName).buy();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    最终使用方式 - 优雅的一行代码

        public Fruit buyFruit2(String name) {
            return BuyFruitFactory.buy(name);
        }
    
    • 1
    • 2
    • 3
  • 相关阅读:
    Vue与relation-graph:高效打造关系图的秘诀
    混淆技术研究笔记(二)yGuard入门
    LeetCode 0895. 最大频率栈
    2020年7月大学英语六级作文
    Activiti可视化流程管理器
    引领数据领域AI工程化落地,为什么会是云测数据?
    集合面试题汇总
    String64类的设计思想
    php练习04
    AirtestIDE编辑窗内,脚本内容消失,显示一片红色怎么办?
  • 原文地址:https://blog.csdn.net/PROGRAM_anywhere/article/details/134451865