首先来看一下这段代码
String name = "李四";
@Test
public void noDesign(){
if ("张三".equals(name)){
System.out.println("张三执行业务");
}else if ("李四".equals(name)){
System.out.println("李四执行业务");
}else if ("王五".equals(name)){
System.out.println("王五执行业务");
}
}
这段代码中只有三个if else,这里我们只是简单模式if else,如果业务逻辑非常复杂,可能会有很多个if else 判断,这时候就会造成代码繁琐,并且不太雅观,后期再维护也会困难。
如何解决?
- 将每个if else if中的业务逻辑(也就是本例中的 System.out.println();)单独抽取成一个handler处理器类
- 将这些处理器类存放到一个Map中,因为在判断时是按照name是否相同来执行相关逻辑的,那我们可以根据这个name,把name当成一个key,从的Map中获取value,也就是对应的handler。
如下所示
@Test
public void withDesign(){
Handler handler = HandlerFactory.getHandler(name);
handler.handler();
}
我们用两行代码就解决了if else问题。那么具体是怎么实现的呢?还是按照我们上面的思路来,刚才我们分析,把if else中的代码都单独抽取成一个handler,那本例的话就是三个handler,那么这个handler类中至少得有个执行业务逻辑的方法,对吧,也就是 System.out.println();而且还要把这个handler放入到Map,也就是说除了执行业务逻辑代码的方法外,还应该有一个注册到Map的方法,而注册的时间应该是应用启动时,那么此时我们就想到了一个接口InitializingBean,这个接口中的afterPropertiesSet恰好是容器启动完成自动回调的,则我们可以在这个方法中实现注册handler的逻辑。
具体实现
- 编写一个Hanler接口,继承InitializingBean,并在该接口中定义一个handler方法,此方法就是执行业务逻辑的方法。
public interface Handler extends InitializingBean {
void handler();
}
- 抽取每个if else if中的代码,独立为一个handler,实现自定义的Handler。
@Component
public class LSHandler implements Handler {
@Override
public void handler() {
System.out.println("李四执行业务");
}
@Override
public void afterPropertiesSet() throws Exception{
HandlerFactory.registerHandler("李四",this);
}
}
张三和王五的Handler都是一样,大家参考即可。
示意图:
- 创建一个工厂类,提供注册Handler和根据key获取Handler的方法
public class HandlerFactory {
public static Map<String,Handler> strategyMap = new HashMap<>();
//根据key获取Handler
public static Handler getHandler(String key){
return strategyMap.get(key);
}
//注册Handler
public static void registerHandler(String key,Handler handler){
if (handler != null && StringUtils.isNotEmpty(key)){
strategyMap.put(key,handler);
}
}
}
此时我们再回看这段代码
@Test
public void withDesign(){
String name = "王五";
Handler handler = HandlerFactory.getHandler(name);
handler.handler();
}
大家是不是就能懂了呢。
优化
大家再来看这样一段代码
if ("张三".equals(name)){
System.out.println("张三执行业务");
}
else if ("李四".equals(name)){
System.out.println("李四执行业务");
}
else if ("王五".equals(name)){
System.out.println("王五执行业务");
}
else if ("赵六".equals(name)){
return UUID.randomUUID().toString();
}
else if ("吕七".equals(name)){
return UUID.randomUUID().toString();
}
我们发现,if else if中的逻辑不再是相同的了,有需要return的,有不需要return的,那此时我们之前那样的设计就行不通了,如果我们将之前自定义的Handler接口定义为这样是否合理?
public interface Handler extends InitializingBean {
void handler();
String handlerWithReturn(String value);
}
显然不太合理,因为这样的话我们之前定义的ZSHandler和LSHandler都要实现handlerWithReturn方法,可问题是这两个Handler的业务逻辑无需这个方法,这样也造成了代码冗余,违背了我们最初的设计原则。
解决
- 将Handler接口改为抽象类,这样在抽象类中就可以写方法体。如下
public abstract class AbstractHandler implements InitializingBean {
public void handler(){
throw new UnsupportedOperationException();
}
public String handlerWithReturn(String value){
throw new UnsupportedOperationException();
}
}
将原本的接口改为抽象类以后,那不同的Handler只需要实现自己的方法即可,如果调用另一个方法,则会抛出异常。
- 现在我们再来看李四的Handler
@Component
public class LSHandler extends AbstractHandler {
@Override
public void handler() {
System.out.println("李四执行业务");
}
@Override
public void afterPropertiesSet() throws Exception{
HandlerFactory.registerHandler("李四",this);
}
}
这个Handler只需要重写handler的方法即可。
- 再来看赵六的Handler
@Component
public class ZLHandler extends AbstractHandler {
@Override
public String handlerWithReturn(String value) {
return "Hello" + value;
}
@Override
public void afterPropertiesSet() throws Exception{
HandlerFactory.registerHandler("赵六",this);
}
}
那现在同样,赵六Handler重写了handlerWithReturn方法,而不用管handler方法。
- 最后记得修改工厂类的Map的value类型
public class HandlerFactory {
public static Map<String,AbstractHandler> strategyMap = new HashMap<>();
//根据key获取Handler
public static AbstractHandler getHandler(String key){
return strategyMap.get(key);
}
//注册Handler
public static void registerHandler(String key,AbstractHandler handler){
if (handler != null && StringUtils.isNotEmpty(key)){
strategyMap.put(key,handler);
}
}
}