策略模式和简单工厂模式替代IF ELSE 和Switch
2020-05-21 本文已影响0人
久伴我还是酒伴我
简介
这两天在搞一个调度任务,通过XXL-JOB定期执行未执行的数据,数据类型大概有八九种,不同的类型不同的业务逻辑处理,需要调用不同的方法进行处理,可能类型少点可以通过IF ELSE 或者Switch 去实现,但是多了,代码看着很不优雅,实在看不下去了,就通过策略模式和简单工厂模式简单改造了下。
改造前
代码中method是实际执行方法,这里咱们用method代替,这么多case 感觉很low
if (CollectionUtils.isNotEmpty(invoiceWbAsynList)) {
invoiceWbAsynList.stream().forEach(v -> {
switch (v.getType()) {
case 0:
case 1:
method1(v);
break;
case 2:
method2(v);
break;
case 3:
method3(v);
break;
case 4:
method4(v);
break;
case 5:
method5(v);
break;
case 6:
method6(v);
break;
case 7:
method7(v);
break;
case 8:
method8(v);
default:
method9(v);
}
});
}
改造后
咱们改造后的再看下,就这么几行代码,瞬间高大上了。
if (CollectionUtils.isNotEmpty(invoiceWbAsynList)) {
invoiceWbAsynList.stream().forEach(v -> {
factoryForStrategy.getStrategy(WbAsynTypeEnum.getVal(v.getType()).getMethod()).execute(v);
});
}
举例
上述代码是实际业务中产生的,为了更直观的了解,咱们举个简单的例子。
当前社会,手机是必不可少的,有很多人都是两三个手机(ps:我只有一个手机),咱们使用不同的手机(苹果、华为、小米、)打电话来模仿再实际业务中要调用不同的方法。
创建 PhoneStrategy
package com.glj.webservice.demo.strategy;
public interface PhoneStrategy {
// 打电话
String call(String phoneName);
}
创建 AppleStrategy
package com.glj.webservice.demo.strategy.impl;
import com.glj.webservice.demo.strategy.PhoneStrategy;
import org.springframework.stereotype.Component;
/**
* 苹果手机打电话
*/
@Component("apple")
public class AppleStrategy implements PhoneStrategy {
@Override
public String call(String phoneName) {
System.out.println("使用"+phoneName+"手机打电话");
return "使用"+phoneName+"手机打电话";
}
}
创建 HuaWeiStrategy
package com.glj.webservice.demo.strategy.impl;
import com.glj.webservice.demo.strategy.PhoneStrategy;
import org.springframework.stereotype.Component;
/**
* 华为手机打电话
*/
@Component("huawei")
public class HuaWeiStrategy implements PhoneStrategy {
@Override
public String call(String phoneName) {
System.out.println("使用"+phoneName+"手机打电话");
return "使用"+phoneName+"手机打电话";
}
}
创建 XiaoMiStrategy
package com.glj.webservice.demo.strategy.impl;
import com.glj.webservice.demo.strategy.PhoneStrategy;
import org.springframework.stereotype.Component;
/**
* 小米手机打电话
*/
@Component("xiaomi")
public class XiaoMiStrategy implements PhoneStrategy {
@Override
public String call(String phoneName) {
System.out.println("使用"+phoneName+"手机打电话");
return "使用"+phoneName+"手机打电话";
}
}
创建简单工厂PhoneStrategyFactory
package com.glj.webservice.demo.strategy.factory;
import com.glj.webservice.demo.strategy.PhoneStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class PhoneStrategyFactory {
@Autowired
Map<String, PhoneStrategy> strategys = new ConcurrentHashMap<>();
public PhoneStrategy getStrategy(String component){
PhoneStrategy strategy = strategys.get(component);
Optional.ofNullable(strategy).orElseThrow(RuntimeException::new);
return strategy;
}
}
关键点: AutoWired一个Map<String, PhoneStrategyFactory > 这个会在初始化的时候将所有的PhoneStrategyFactory 实现类自动加载到Map中。使用concurrentHashMap是防止多线程操作的时候出现问题。同时还要注意@Service注解。
Swagger测试
请求参数和结果
image.pngimage.png
结束语:
其实策略模式在我们日常开发中,不管是算法还是业务逻辑处理,主要是针对相同请求参数和相同的返回参数,不同的业务处理,用到的概率会很多,如果请求参数不一致,或者返回参数不一致,策略模式还是不建议使用的(除非通过泛型或者特殊手段处理)。