作用
在日常开发中,我们常常会遇到一个接口有多个实现类时,需要选择合适的实现类的情况。
最简单的方法是写一个选择器,用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());
}
}