• 你还在用if-else吗?


    使用spring容器干掉if-else

    场景说明

    最近新做一个项目,需要对不同店铺的商品做不同处理。例如storeA需要进行handleA操作,storeB需要进行handleB操作,如此类推。

    大家很容易会想到下面的实现方法

    public void handle(String storeName) {
        //店铺A做操作handleA处理
        if(storeName.equals("storeA")) {
            handleA();
        } else if (storeName.equals("storeB")) {
            handleB(); //店铺B做操作handleB处理
        } else {
            //其他处理
        }
    }
    

    确实上面的代码实现简单易懂,但是如果店铺越来越多,操作也越来越多的情况下,每新增一个店铺都需要在这里添加一次if else,并且都要在原有的代码上进行修改,耦合度太高,也大大的降低了代码的可维护性。
    因此引入本文的重点。

    解决办法

    这个时候我们会希望可以各个店铺的处理逻辑之间没有关联,互不影响。

    抽象接口

    我们所有的店铺都会进行对应的操作,所以首先我们将方法抽象出来

    public interface Store {
        void handle();
    }
    

    根据不同店铺做不同处理

    @Service("storeA")
    public class StoreA implements Store {
        @Override
        void handle() {
            //handleA操作
        }
    }
    @Service("storeB")
    public class StoreB implements Store {
        @Override
        void handle() {
            //handleB操作
        }
    }
    

    添加工厂类

    这样还是有问题,因为还是要在业务代码中写if-else来判断到底是哪家store来进行操作,这个时候可以写一个工厂类。

    
    public class StoreFactory {
    
        @Autowired
        @Qualifier("storeA")
        private StoreA storeAA;
    
        @Autowired
        @Qualifier("storeB")
        private StoreB storeBB;
        
        //其他实现对象
    
        public Store getStore(String storeName) {
    
            if (storeName.equals("storeA")) {
                return storeAA;
            } else if (storeName.equals("storeB")) {
               return storeBB;
            }//其他的条件下,返回其他的对象
        }
    
    }
    

    添加工厂类后,我们在要获取店铺store时只需要调用getStore(String storeName)并传入店铺对象名即可,具体返回哪个对象,是storeA还是storeB,就交给工厂类来处理。

    还是免不了写if else,改造StoreFactory

    在提供了工厂类之后,还是免不了写很多的条件判断,只不过是把所有的条件判断写在了一起。这时随着产品数量的增多,if else 也会不停地增多,维护起来依然费劲。
    这里spring容器就可以派上用场了。spring中有一个BeanFactory对象,也是一个工厂,我们可以用它来改造StoreFactory。

    public class StoreFactory {
        @Autowired
        private BeanFactory beanFactory;
        
        public Store getStore(String storeName) {
            Object bean = beanFactory.getBean(storeName);
            if (bean instanceof Store) {
                return (Store) bean;
            }
            throw new UnsupportedOperationException("不支持的店铺:" + storeName);
        }
    }
    

    也可以利用Map自动装配进行代码精简

    @Service
    public class StoreFactory {
    
        @Autowired
        Map<String, Store> stores = new ConcurrentHashMap<>(); //会在初始化的时候将所有的Store自动加载到Map中
    
        public Store getStore(String store) {
            Store store = stores.get(store);
            if (store == null) {
                throw new RuntimeException("no store defined");
            }
            return store;
        }
    }
    

    @Autowired的源码中有这样一段注释,大意就是@Autowired用于Collection或者Map类型时,容器会自动装配所有已声明的value类型的beans。

    /* <p>In case of a {@link java.util.Collection} or {@link java.util.Map} dependency type,
     * the container autowires all beans matching the declared value type. For such purposes,
     * the map keys must be declared as type String which will be resolved to the corresponding
     * bean names. Such a container-provided collection will be ordered, taking into account
     * {@link org.springframework.core.Ordered}/{@link org.springframework.core.annotation.Order}
     * values of the target components, otherwise following their registration order in the
     * container. Alternatively, a single matching target bean may also be a generally typed
     * {@code Collection} or {@code Map} itself, getting injected as such.
     */
    

    最后

    以上就是全部内容。
    欢迎转载,转载请说明出处:https://www.cnblogs.com/perryzjl/p/11097106.html

  • 相关阅读:
    非常有助于理解二极管PN结原理的资料
    5个CSS3技术实现设计增强
    如何读懂Web服务的系统架构图
    网页布局WEB标准的HTML结构化
    网站内容排版可用性分析
    用CSS做导航菜单的4个理由
    提高网站设计可用性(有效性)的10条原则
    dl,dt,dd标签 VS 传统table实现数据列表
    一些CSS3新技术
    21个CSS技巧
  • 原文地址:https://www.cnblogs.com/perryzjl/p/11097106.html
Copyright © 2020-2023  润新知