zoukankan      html  css  js  c++  java
  • 一种简洁的Spring Bean选择器模式

    作用

    在日常开发中,我们常常会遇到一个接口有多个实现类时,需要选择合适的实现类的情况。

    最简单的方法是写一个选择器,用if-else来判断使用哪个实现类的实例,比如:

    if(条件1){
      return 实现类a的实例;
    }else if(条件2){
      retuen 实现类b的实例;
    }
    

    然而这种方法不符合开闭原则(OCP),如果再添加一个实现类,那么选择器的代码也需要再加一个else if。

    所以,在参考了同事及网上的一些代码后,我整理出了一种简洁的、符合设计原则的实现方式。

    一种更好的选择器:工具类

    这种选择器使用了策略模式,并且利用了Spring的自动注入特性。

    首先,我们需要提供4个工具类:

    public interface MatchingBean<K> {
        boolean matching(K factor);
    }
    
    public interface MyFactoryList<E extends MatchingBean<K>, K> extends List<E> {
        E getBean(K factor);
        List<E> getBeanList(K factor);
    }
    
    public class MyFactoryArrayList<E extends MatchingBean<K>, K> extends ArrayList<E>
            implements MyFactoryList<E, K>, Serializable {
        @Override
        public E getBean(K factor) {
            Iterator<E> itr = iterator();
            while (itr.hasNext()) {
                E beanMatch = itr.next();
                if (beanMatch.matching(factor)) {
                    return beanMatch;
                }
            }
            return null;
        }
        @Override
        public List<E> getBeanList(K factor) {
            Iterator<E> itr = iterator();
            while (itr.hasNext()) {
                E beanMatch = itr.next();
                if (!beanMatch.matching(factor)) {
                    itr.remove();
                }
            }
            return this;
        }
    }
    
    public class MyFactoryListEditor extends CustomCollectionEditor {
        public MyFactoryListEditor() {
            super(MyFactoryArrayList.class);
        }
    }
    

    一种更好的选择器:使用示例

    假设我们有个购物接口,有淘宝和京东两个实现。

    那么就让购物接口继承MatchingBean,代码如下:

    public interface BuyService extends MatchingBean<String> {
        public String goShopping();
    }
    

    然后在实现类里实现matching方法,代码如下:

    @Service
    public class JingdongService  implements BuyService {
    
        @Override
        public String goShopping() {
            return "Shopping in Jd";
        }
    
        @Override
        public boolean matching(String factor) {
            return "jd".equals(factor);
        }
    }
    
    @Service
    public class TaobaoService implements BuyService {
    
        @Override
        public String goShopping() {
            return "Shopping in Taobao";
        }
    
        @Override
        public boolean matching(String factor) {
            return "taobao".equals(factor);
        }
    }
    

    最后,咱们写个测试类,看下选择器的使用方法:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class TestMyBeanUtil {
    
        @Autowired
        MyFactoryList<BuyService,String> factoryList;
    
        @Test
        public void testOne(){
            BuyService shop = factoryList.getBean("jd");
            System.out.println(shop.goShopping());
        }
    }
    

    参考文献

    https://my.oschina.net/guanhe/blog/1821060

  • 相关阅读:
    遇到shell重定向的一个奇怪问题:'消失'的标准输入!
    步步深入:MySQL架构总览->查询执行流程->SQL解析顺序
    [来自妹纸的挑战]-展开/还原多层链表
    【Shell】Linux 一行 多命令
    【Shell】通配符与特殊符号
    【Shell】变量的取用、删除、取代与替换
    【LeetCode】Find Minimum in Rotated Sorted Array 在旋转数组中找最小数
    【LeetCode】Maximum Product Subarray 求连续子数组使其乘积最大
    【LeetCode】Reverse Words in a String 反转字符串中的单词
    【面试题】比给定数大的最小数
  • 原文地址:https://www.cnblogs.com/bailiyi/p/12115027.html
Copyright © 2011-2022 走看看