一种简洁的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

上一篇:fsockopen无法正常使用FastCGI(PHP)


下一篇:nohup: ignoring input and appending output to ‘nohup.out‘ 后台命令错误解决办法