(策略模式+工厂模式+map)套餐 Kill 项目中的switch case

栏目: 后端 · 发布时间: 5年前

内容简介:接手新任务:接入第三家存证机构,看之前的代码使用了swith case判断使用哪家存证机构,每家存证机构的实现逻辑不一样 代码的坏味道:多层swich case。多层swich case不好维护,是时候应该重构了,为了便于理解,举个没有业务逻辑的例子,基于这个例子上进行优化。 现在是12:47,举个饭后吃水果的例子哈哈哈(逃 假设我们可以选择的水果有香蕉、西瓜和苹果。吃香蕉的话我们得先剥皮,吃西瓜的话得先用水果刀切一下,如果是苹果的话就直接吃了。将这个场景转化为代码:这个例子代码量不是很大,但是实际项目中

接手新任务:接入第三家存证机构,看之前的代码使用了swith case判断使用哪家存证机构,每家存证机构的实现逻辑不一样 代码的坏味道:多层swich case。多层swich case不好维护,是时候应该重构了,

优化前的代码

为了便于理解,举个没有业务逻辑的例子,基于这个例子上进行优化。 现在是12:47,举个饭后吃水果的例子哈哈哈(逃 假设我们可以选择的水果有香蕉、西瓜和苹果。吃香蕉的话我们得先剥皮,吃西瓜的话得先用水果刀切一下,如果是苹果的话就直接吃了。将这个场景转化为代码:

public class EatFruit {
    private static final String APPLE = "apple";
    private static final String BANANA = "banana";
    private static final String WATERMELON = "watermelon";

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //选择的水果种类
        String fruitType = scanner.nextLine();

        switch (fruitType) {
            case APPLE:
                eatApple();
                break;
            case BANANA:
                eatBanana();
                break;
            case WATERMELON:
                eatWatermelon();
                break;
        }
    }

    private static void eatBanana() {
        System.out.println("吃香蕉了,需要先剥下皮");
    }

    private static void eatApple() {
        System.out.println("是苹果,可以直接吃");
    }

    private static void eatWatermelon() {
        System.out.println("吃西瓜了,但是还得弄把水果刀切一下先");
    }
}
复制代码

这个例子代码量不是很大,但是实际项目中的场景肯定没有这么简单,多重swich case不好维护,并且万一又加了一样水果,还得继续加一层case...

(策略模式+工厂模式+map)套餐 Kill 项目中的switch case

很容易想到策略模式(简单的理解就是多态),水果都有吃的一个动作,但是每种水果的吃法不一样

使用策略模式进行优化

Fruit.java

public interface Fruit {
    void eat();
}

复制代码

Apple.java

public class Apple implements Fruit {
    @Override
    public void eat() {
        System.out.println("是苹果,可以直接吃");
    }
}
复制代码

Banana.java

public class Banana implements Fruit {
    @Override
    public void eat() {
        System.out.println("吃香蕉了,需要先剥下皮");
    }
}
复制代码

Watermelon.java

public class Watermelon implements Fruit {
    @Override
    public void eat() {
        System.out.println("吃西瓜了,但是还得弄把水果刀切一下先");
    }
}
复制代码

但是发现即使用了策略模式也难逃类型判断 EatFruit.java

public class EatFruit {
    private static final String APPLE = "apple";
    private static final String BANANA = "banana";
    private static final String WATERMELON = "watermelon";

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //选择的水果种类
        String fruitType = scanner.nextLine();
        Fruit fruit = null;

        switch (fruitType) {
            case APPLE:
                fruit = new Apple();
                break;
            case BANANA:
                fruit = new Banana();
                break;
            case WATERMELON:
                fruit = new Watermelon();
                break;
        }

        fruit.eat();
    }
}
复制代码

使用策略模式具有良好的扩展性,兵来将挡,再给我添加十种水果都不怕,水果种类太多会使水果的实现类暴增。现在来一种水果无需在原先的业务类(EatFruit)里修改很多的代码逻辑,只要实现接口并加个条件判断就好了。但是使用策略模式时,我们需要知道具体的实现类,具体的实现类需要对外暴露

使用工厂模式

将类型判断放到工厂类中 工厂模式:在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象,这里共同的接口就是Fruit。粗暴的讲,工厂模式就是把创建同一类型对象逻辑写在了一个方法里 FruitFactory .java

public class FruitFactory {
    public static Fruit getFruit(String fruitType) {
        if ("apple".equals(fruitType)) {
            return new Apple();
        }

        if ("banana".equals(fruitType)) {
            return new Banana();
        }

        return new Watermelon();
    }
}
复制代码

EatFruit .java

public class EatFruit {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //选择的水果种类
        String fruitType = scanner.nextLine();
        Fruit fruit = FruitFactory.getFruit(fruitType);
        fruit.eat();
    }
}
复制代码

到现在为止EatFruit中的业务代码已经很清晰了。 使用工厂模式具有良好的封装性,这下妈妈再也不用关系创建类的过程,甚至连创建的实际类的都无需关心,实现了解耦,实际类的修改变化都不会影响上层业务

但是工厂类中还是有很多if的,革命尚未成功,仍需要进行优化。

map奥特曼来了

FruitFactory.java

public class FruitFactory {
    private static Map<String, Fruit> fruitMap = new HashMap<>();

    static {
        fruitMap.put("apple", new Apple());
        fruitMap.put("banana", new Banana());
        fruitMap.put("watermelon", new Watermelon());
    }

    public static Fruit getFruit(String fruitType) {
       return fruitMap.get(fruitType);
    }
}
复制代码

通过使用map, fruitType<T extend Fruit> 进行一一映射,和条件判断说byebye~,代码也很优雅 最终项目结构类图:

(策略模式+工厂模式+map)套餐 Kill 项目中的switch case

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Head First JavaScript程序设计

Head First JavaScript程序设计

[美]Eric T. Freeman、[美] Elisabeth Robson / 袁国忠 / 人民邮电出版社 / 2017-9 / 129.00 元

本书语言和版式活泼,内容讲解深入浅出,是难得的JavaScript入门书。本书内容涵盖JavaScript的基本知识以及对象、函数和浏览器文档对象模型等高阶主题。书中配备了大量有趣的实例、图示和练习,让读者轻轻松松掌握JavaScript。一起来看看 《Head First JavaScript程序设计》 这本书的介绍吧!

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具