程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

工厂模式+策略模式消除 if else 实战

balukai 2025-07-10 13:15:55 文章精选 4 ℃

一、为什么需要工厂模式+ 策略模式?

单独使用策略模式时,客户端需要直接实例化具体策略类(如 new AiAuditStrategy()),这会导致两个问题:

  • 客户端与具体策略强耦合:客户端必须知道所有策略类的细节(如类名、构造参数),违反 “迪米特法则”。
  • 策略创建逻辑重复:若策略的创建需要复杂逻辑(如参数校验、依赖注入、配置读取),这些代码会在客户端重复出现,违背 “单一职责原则”。

而工厂模式的核心是封装对象创建逻辑,通过工厂类统一管理策略的实例化过程。两者结合后,客户端只需通过工厂获取策略实例(如
AiAuditStrategyFactory.getMediaType(1)),无需关心具体策略如何创建或切换,同时保持策略的动态替换能力。

二、工厂模式 + 策略模式解决的核心问题

1. 解耦客户端与具体策略

客户端只需通过工厂获取策略接口,无需知道具体策略类的细节(如类名、构造参数),符合 “依赖倒置原则”。

2. 封装复杂的创建逻辑

策略的创建可能涉及参数校验、资源初始化(如数据库连接)、配置读取等逻辑,这些代码被集中封装在工厂中,避免重复。

3. 支持动态切换策略

通过工厂的 “类型参数” 或 “配置”,可以在运行时动态选择策略(如根据用户选择切换支付方式),无需修改客户端代码。

4. 符合开闭原则

新增策略时,只需添加新的策略类和工厂的创建逻辑(如在工厂中注册新策略类型),无需修改现有客户端代码,扩展性强。

三、工厂模式 + 策略模式实战

3.1 需求

有个后台管理系统,可以上传不同的资源类型(图片、音频和视频),上传后调用第三方接口进行机审,要求:尽可能少用 if else 、易维护、易扩展和增加策略后不需要修改客户端代码。


3.2 if else 实现

业务实现代码:

public interface AudioAuditService {
    void audit(Integer mediaType);
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class AudioAuditServiceImpl implements AudioAuditService {
    
    public void audit(Integer mediaType) {
        log.info("## audit param mediaType:{}", mediaType);
        if (mediaType == 1) {
	        // 业务实现简略
    		System.out.println("视频机审, 调用腾讯AI机审接口");
        } else if (mediaType == 2) {
        	// 业务实现简略
    		System.out.println("音频机审, 调用腾讯AI机审接口");
        } else if (mediaType == 3) {
        	// 业务实现简略
    		System.out.println("图片机审, 调用腾讯AI机审接口");
        }
    }
}

客户端代码:

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class AudioAuditServiceImpl implements AudioAuditService {
    
    public void audit(Integer mediaType) {
        log.info("## audit param mediaType:{}", mediaType);
        if (mediaType == 1) {
	        // 业务实现简略
    		System.out.println("视频机审, 调用腾讯AI机审接口");
        } else if (mediaType == 2) {
        	// 业务实现简略
    		System.out.println("音频机审, 调用腾讯AI机审接口");
        } else if (mediaType == 3) {
        	// 业务实现简略
    		System.out.println("图片机审, 调用腾讯AI机审接口");
        }
    }
}

使用postman模拟请求:

执行结果截图:


3.3 工厂模式 + 策略模式实现

策略类:

public interface AiAuditStrategy {

    default void audit() {
        throw new RuntimeException("此资源类型没有AI审核!");
    }
}

工厂类:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class AiAuditStrategyFactory {
	
	// 使用ConcurrentHashMap管理所有的策略,避免并发请求产生线程安全问题
    private static Map<Integer, AiAuditStrategy> map = new ConcurrentHashMap<>();

    public static AiAuditStrategy getMediaType(Integer type) {
        return map.get(type);
    }

    public static void register(Integer type, AiAuditStrategy strategy) {
        map.put(type, strategy);
    }
}


以下策略实现类均通过 Spring 的 InitializingBean 注册策略类

视频策略实现:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

@Service
public class VideoAiAuditStrategy implements AiAuditStrategy, InitializingBean {

    @Override
    public void afterPropertiesSet() {
        AiAuditStrategyFactory.register(1, this);
    }

    @Override
    public void audit() {
    	// 业务实现简略
    	System.out.println("策略模式-视频机审, 调用腾讯AI机审接口");
	}

}

音频策略实现:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

@Service
public class AudioAiAuditStrategy implements AiAuditStrategy, InitializingBean {

    @Override
    public void afterPropertiesSet() {
        AiAuditStrategyFactory.register(2, this);
    }

    @Override
    public void audit() {
    	// 业务实现简略
    	System.out.println("策略模式-音频机审, 调用腾讯AI机审接口");
	}

}

图片策略实现:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

@Service
public class ImageAiAuditStrategy implements AiAuditStrategy, InitializingBean {

    @Override
    public void afterPropertiesSet() {
        AiAuditStrategyFactory.register(3, this);
    }

    @Override
    public void audit() {
    	// 业务实现简略
    	System.out.println("策略模式-图片机审, 调用腾讯AI机审接口");
	}

}

客户端代码:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/media-resources")
public class MediaResourcesController {
    @Autowired
    private AudioAuditService audioAuditService ;

    @PostMapping("/audit2")
    public String audit2(@RequestParam Integer mediaType) {
        AiAuditStrategyFactory.getMediaType(mediaType).audit();
        return "OKK";
    }
}

使用postman模拟请求:

执行结果截图:


工厂加策略模式完美实现上述需求,消除 if else 、易维护、易扩展、增加策略后不需要修改客户端代码,直接添加策略类即可。



– 欢迎点赞、关注、转发、收藏【技术咖啡馆C】,各大平台同名。

最近发表
标签列表