一个接口有多个实现类,@Autowired注入map方式初始化实现类并统一调用(策略模式)

使用原因和场景

在工作中经常会遇到一个接口有很多实现类,然后需要定义一个统一的入口去调用,如果每次都注入不同的实现类,不符合Java的对开放-关闭原则(Open-Closed Principle, OCP),且代码冗余不好看。

//使用了策略模式
	@Autowired
    private Map<String, OrderService> beanFactory;
    
   //第二种
   @Autowired
   private Map<String, OrderService> beanFactory = Maps.newConcurrentMap();(这两个都可以)

Spring 会在启动时,自动查找实现了该接口的 bean,放到这个Map中去。 key为bean的名字,value为 实现了该接口的所有的 bean。

注意:这里只有在map的key为string类型时才有效;

具体的代码实现

1、定义接口的调用工厂

初始化所有的OrderService实现类并通过OrderFactory 来调用具体的实现类
Map<String, OrderService> String参数 是定义的service的类名,可以使用@Component(“AA”) 重命名为AA

@Slf4j
@Service
public class OrderFactory {
    /**
    *策略模式
    *会在spring启动时把所有OrderService加载到map中
    *关键在于 @Autowired
    **/
// ❌ 风险:手动初始化可能覆盖Spring注入的Map内容
//@Autowired
//private Map<String, OrderService> beanFactory = Maps.newConcurrentMap();

// ✅ 修正:依赖Spring自动注入,无需手动初始化
@Autowired
private Map<String, OrderService> beanFactory;

    public OrderService get(String key){
        OrderService orderService = beanFactory.get(key);
        if(orderService == null) {
            throw new RuntimeException("no OrderService defined!");
        }
        return orderService;
    }

    public void put(String key, OrderService service){
        beanFactory.put(key, service);
    }

}

2、定义接口类

定义一个接口,用于提供统一的调用方法

public interface OrderService{
    /**
     *处理订单
     * @params orderNo 订单号
     * @params orderType 订单类型
    * */
    String dealOrdering(String orderNo,String orderType );
}
3、定义接口抽象实现类

定义一个抽象类,实现OrderService接口,提供多个实现类的通用方法,并提供一个业务逻辑处理抽象方法,让具体实现类各自实现自己的业务逻辑。所有通用的逻辑都可以抽出来,放在这个类里面处理。

public abstract class OrderAbstractService implements OrderService{
   
	//提供统一的逻辑校验等方法
    public boolean checkRepay(String orderNo,String orderType ){
    	Boolean check=false;
		//可以进行防重复校验
		//日志记录
		//其他
        return check;
    }

	//重写接口方法,做一些通用的逻辑处理,比如防重等
    @Override
    public String dealOrdering(String orderNo,String orderType ){
        //1.防重校验,如果校验为true,则不需要走dealOrder方法,直接返回Success
        if( checkRepay(orderNo,orderType )){
            return "Success";
        }

         return dealOrder(orderNo,orderType );
    }

	//抽象方法,各自具体实现类的逻辑处理
    public abstract String dealOrder(String orderNo,String orderType);

}
4、定义接口的多个实际业务实现类

下方是三个具体的实现类,继续抽象类OrderAbstractService ,实现各自业务逻辑

@Slf4j
@Component("OrderBenchiCar")
public class OrderBenchiCarService extends OrderAbstractService {

	//实现抽象类的dealOrder,具体实现逻辑处理
    @Override
    public String dealOrder(String orderNo,String orderType) {
		String returnMsg="";
        //2.处理奔驰汽车订单的生产逻辑
      
        //3.调用结果
        return returnMsg;
    }
}

@Slf4j
@Component("OrderBaomaCar")
public class OrderBaomaCarService extends OrderAbstractService {

	//实现抽象类的dealOrder,具体实现逻辑处理
    @Override
    public String dealOrder(String orderNo,String orderType) {
		String returnMsg="";
        //2.处理宝马汽车订单的生产逻辑
      
        //3.调用结果
        return returnMsg;
    }
}

@Slf4j
@Component("OrderAodiCar")
public class OrderAodiCarService extends OrderAbstractService {

	//实现抽象类的dealOrder,具体实现逻辑处理
    @Override
    public String dealOrder(String orderNo,String orderType) {
		String returnMsg="";
        //2.处理奥迪汽车订单的生产逻辑
      
        //3.调用结果
        return returnMsg;
    }
}
5、实际业务调用类

该类为所有此类型业务处理的统一入口,用来接收不同业务类型,然后进行统一调用处理

@Slf4j
@Service
public class OrderControl {

	//统一入口方法,根据传入的ordertype来决定具体的实现类	
	//@Async代表异步处理,也可不用,看具体场景
 	@Async
    public void commit(String orderNo,String orderType)  {
    	String Msg="";//定义返回参数
    	//orderType 为实现类的别名 OrderAodiCar OrderBaomaCar OrderBenchiCar
    	//1.所有类型都直接调用即可
    	Msg= OrderFactory.get(orderType).dealOrdering(orderNo, orderType);
		//2.其他逻辑处理
		if("OrderBenchiCar".equals(orderType)){
			//其他逻辑
			if("Success".equals(Msg)){
			....
			}
		}else if("OrderBenchiCar".equals(orderType)){
		
		}else if("OrderBenchiCar".equals(orderType)){
			
		}
    	
	}
}
### 业务层接口实现类的设计模式分析 在 JavaSpring 开发中,业务层接口及其对应的实现类通常是基于面向对象编程原则和设计模式构建的。以下是关于如何设计和实现这些组件的具体说明。 #### 面向接口编程的重要性 Spring 框架提倡 **面向接口编程** 的理念,这意味着开发者应该优先定义接口将其作为依赖注入的核心部分[^1]。这种方式可以提高代码的可测试性和灵活性,同时便于后续的功能扩展或替换具体实现逻辑。 #### 使用工厂方法模式支持动态切换实现 当存在多个不同的业务处理需求时,可以通过引入 **工厂方法模式** 来动态选择具体的实现类。例如: ```java public interface BusinessService { void process(); } public class ServiceA implements BusinessService { @Override public void process() { System.out.println("Processing with Service A"); } } public class ServiceB implements BusinessService { @Override public void process() { System.out.println("Processing with Service B"); } } ``` 接着,利用工厂方法模式创建合适的 `BusinessService` 实例: ```java public abstract class BusinessFactory { public static BusinessService getBusinessService(String type) { switch (type.toLowerCase()) { case "a": return new ServiceA(); case "b": return new ServiceB(); default: throw new IllegalArgumentException("Unknown service type: " + type); } } } ``` 上述代码展示了如何通过抽象工厂方法返回不同类型的业务服务实例。 #### 单例模式的应用场景 如果某些业务逻辑需要在整个应用生命周期内保持一致状态,则可以考虑采用 **单例模式** 将其实现为全局唯一的实例。例如,在配置加载器或者缓存管理器等模块中经常使用此模式[^3]。 ```java @Component public class ConfigLoader { private static final ConfigLoader INSTANCE = new ConfigLoader(); private Map<String, String> configMap; private ConfigLoader() { this.configMap = loadConfigurations(); // 假设这是一个初始化函数 } public static ConfigLoader getInstance() { return INSTANCE; } private Map<String, String> loadConfigurations() { // 加载配置文件或其他数据源的内容 return Collections.emptyMap(); // 示例占位符 } public String getConfigValue(String key) { return configMap.get(key); } } ``` 在此例子中,`ConfigLoader` 类仅允许创建一次实例,对外暴露静态获取方法以便于调用者访问共享资源。 #### 结合 Spring 容器特性优化设计 借助 Spring IOC/DI 功能,还可以进一步简化传统手动编码中的复杂关系维护工作。比如将上面提到的服务注册到容器里通过自动装配机制完成绑定操作: ```java @Service @Qualifier("serviceA") public class ServiceAImpl implements BusinessService { ... } @Service @Qualifier("serviceB") public class ServiceBImpl implements BusinessService { ... } ``` 之后可以在控制器或者其他地方轻松声明所需版本即可: ```java @Autowired @Qualifier("serviceA") private BusinessService businessService; ``` 这样不仅减少了显式的条件判断语句数量,还增强了程序结构清晰度以及后期维护便利程度[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值