使用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

最新文章

  1. 4.Struts2转向类型详解
  2. FatMouse的交易问题
  3. concurrency parallel 并发 并行
  4. OWASP
  5. HDU 1452 Happy 2004(因子和的积性函数)
  6. Inaccurate values for &ldquo;Currently allocated space&rdquo; and &ldquo;Available free space&rdquo; in the Shrink File dialog for TEMPDB only
  7. zookeeper入门必读
  8. 只响应ccTouchBegan的问题
  9. 使用DatagramSocket与DatagramPacket传输数据
  10. sql语句用&#39;in&#39;执行多条语句时候,执行错误的解决方法
  11. ASP.NET AJAX注册命名空间
  12. Charles Proxy代理使用简要说明
  13. crontab的两大坑:百分号和环境变量
  14. 浅谈 Axios 在 Vue 项目中的使用
  15. React 语法之let和const命令
  16. [vue开发记录]vue仿ios原生datepicker实现
  17. java常见报错及解决
  18. css处理文本溢出
  19. 【金色】种瓜得瓜,种豆得豆 Gym - 102072H (线段树)
  20. href=&quot;javacript:;&quot; href=&quot;javacript:void(0);&quot; href=&quot;#&quot;区别。。。

热门文章

  1. uva 11552 Fewest Flops 线性dp
  2. 【oracle ocp 知识点二】
  3. [C++] 反编译器
  4. python栈--字符串反转,括号匹配
  5. WPF程序加入3D模型
  6. C++ Primer 学习笔记_104_特殊工具与技术 --嵌套类
  7. 卷积(convolution)与相关(correlation)(matlab 实现)
  8. TCP网络通讯如何解决分包粘包问题(有模拟代码)
  9. nyoj 92 图片实用面积【bfs】
  10. 新秀翻译(一个)——Java在继承和组合