详解 策略模式+工厂模式解决if else 冗余问题

首先来看一下这段代码

 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);
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值