场景说明

最近新做一个项目,需要对不同店铺的商品做不同处理。例如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.
*/

spring容器干掉if-else的更多相关文章

  1. 一次项目代码重构-使用spring容器干掉条件判断

    一次项目代码重构-使用spring容器干掉条件判断 这是在一次公司项目中进行重构时,一些复杂业务时想到的一个去掉一些if else的办法.能够使代码逻辑更加清晰,减少一些业务上的耦合. 业务说明 我所 ...

  2. 使用spring容器干掉if-else

    spring容器干掉if-else 场景说明 最近新做一个项目,需要对不同店铺的商品做不同处理.例如storeA需要进行handleA操作,storeB需要进行handleB操作,如此类推 大家很容易 ...

  3. 一则spring容器启动死锁问题(DefaultListableBeanFactory/DefaultSingletonBeanRegistry)

    线上发现一个问题,应用在启动时会卡死,log上并没有什么异常输出,初判应该是死锁问题. 抓现场的thread dump文件, 确实是有两个线程有deadlock问题. 线程一 "HSFBiz ...

  4. Spring容器深入(li)

    spring中最常用的控制反转和面向切面编程. 一.IOC IoC(Inversion of Control,控制倒转).对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的 ...

  5. 通过单元测试理解spring容器以及dubbo+zookeeper单元测试异常处理

    一.先说一个结论:单元测试与主项目的spring容器是隔离的,也就是说,单元测试无法访问主项目spring容器,需要自己加载spring容器. 接下来是代码实例,WEB主项目出于运行状态,单元测试中可 ...

  6. 同时使用Junit4的@Parameterized参数化测试和Spring容器

    转载:http://www.jianshu.com/p/d191fe54915f 整合Spring容器 @SpringApplicationConfiguration(classes = Applic ...

  7. Spring 容器

    Spring提供了两个核心接口:BeanFactory和ApplicationContext,其中applicationContext是BeanFactory的子接口. 他们都可代表Spring容器, ...

  8. Spring-Context之四:Spring容器及bean的定义

    Spring框架的核心功能之一就是控制反转(Inversion of Control, IoC),也叫做依赖注入(dependency injection, DI).关于依赖注入的具体内容可以参见Ma ...

  9. spring容器对bean生命周期的管理三中方式

    spring容器对bean的生命周期管理主要在两个时间点:bean的初始化完成(包括属性值被完全注入),bean的销毁(程序结束,或者引用结束)方式一:使用springXML配置中的init-meth ...

随机推荐

  1. Android Drawable和Bitmap区别

    一.相关概念 1.Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable) ...

  2. byte[],File和InputStream的相互转换

    File.FileInputStream 转换为byte[] File file = new File("test.txt"); InputStream input = new F ...

  3. Go语言入门——函数

    写了快一个月的Go,已经没有什么陌生感了. 一行代码写完,不会在行尾本能的敲上“:”,直接Enter键换行: 定义变量把变量名放在前面,类型放在后面: 使用struct去定义自己想要的数据模型就好比定 ...

  4. CSS选择符总结(Selectors)

    一.通配选择符(Universal Selector):    语法:*    说明:1.*表示通配符,表示所有的            2.格式:*{样式列表}            3.用于整个页 ...

  5. dfs 解决八皇后问题 以及其他图搜索问题

    33. N皇后问题 中文 English n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击(任意两个皇后不能位于同一行,同一列,同一斜线). 给定一个整数n,返回所有不同的n皇后问 ...

  6. 《快活帮》第八次团队作业:Alpha冲刺

    项目 内容 这个作业属于哪个课程 2016计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十二 团队作业8-软件测试与ALPHA冲刺 团队名称 快活帮 作业学习目标 (1)掌握 ...

  7. datagrid 文本溢出时候 鼠标经过出现提示信息tooltip

    1只有文本溢出的单元格鼠标经过才显示提示信息 $('.datagrid-cell').mouseover(function () { if (this.offsetWidth < this.sc ...

  8. CSS float 父元素高度自适应

    <html> <head><title></title><style type="text/css">*{margin: ...

  9. CF528D Fuzzy Search 和 BZOJ4259 残缺的字符串

    Fuzzy Search 给你文本串 S 和模式串 T,求 S 的每个位置是否能模糊匹配上 T. 这里的模糊匹配指的是把 T 放到 S 相应位置上之后,T 中每个字符所在位置附近 k 个之内的位置上的 ...

  10. Opencv python图像处理-图像相似度计算

    一.相关概念 一般我们人区分谁是谁,给物品分类,都是通过各种特征去辨别的,比如黑长直.大白腿.樱桃唇.瓜子脸.王麻子脸上有麻子,隔壁老王和儿子很像,但是儿子下巴涨了一颗痣和他妈一模一样,让你确定这是你 ...