策略模式和简单工厂模式替代IF ELSE 和Switch

简介

这两天在搞一个调度任务,通过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 strategys = new ConcurrentHashMap<>();

    public PhoneStrategy getStrategy(String component){
        PhoneStrategy strategy = strategys.get(component);
        Optional.ofNullable(strategy).orElseThrow(RuntimeException::new);
        return strategy;
    }
}

关键点: AutoWired一个Map 这个会在初始化的时候将所有的PhoneStrategyFactory 实现类自动加载到Map中。使用concurrentHashMap是防止多线程操作的时候出现问题。同时还要注意@Service注解。

Swagger测试

请求参数和结果

image.png

image.png

结束语:
其实策略模式在我们日常开发中,不管是算法还是业务逻辑处理,主要是针对相同请求参数和相同的返回参数,不同的业务处理,用到的概率会很多,如果请求参数不一致,或者返回参数不一致,策略模式还是不建议使用的(除非通过泛型或者特殊手段处理)。

你可能感兴趣的:(策略模式和简单工厂模式替代IF ELSE 和Switch)