Java Spring场景下多共享代码适配器的最优设计方案咨询
多组件适配器场景下的最优设计方案
核心思路:基于组合+分层抽象的适配架构
针对你这种「适配器由多交互类组成、仅底层组件有微小差异、大部分逻辑共享」的场景,核心是把适配器拆分为通用上层组件和差异化底层组件,通过抽象层隔离变化,再结合Spring特性实现灵活装配——既不用让工厂全权组装所有部件,也不能把判定逻辑全丢给适配器自身。
具体方案拆解
1. 分层抽象适配器组件
先按职责把适配器拆成三层,明确哪些是通用逻辑、哪些是差异化逻辑:
- 顶层适配入口:定义统一的
DataAdapter接口,暴露fetchData()等核心方法,对业务层完全屏蔽外部系统细节。 - 通用中间层:比如
DataParser、RequestBuilder这类大部分适配器共享的逻辑,抽象为接口+默认实现(用抽象类或Spring 6+的@DefaultImplementation),仅预留差异化扩展点。 - 底层差异化组件:比如针对不同协议变体的
ProtocolHandler、PayloadConverter,每个变体对应一个实现类,用自定义注解(如@AdapterType("PROTOCOL_V1"))标记类型标识。
2. 用「工厂+策略模式」替代全量构建器
不要让工厂负责所有组件的组装,而是聚焦根据外部系统类型匹配底层差异化组件,通用组件直接复用Spring容器中的单例:
- 定义
AdapterFactory,通过@Autowired Map<String, ProtocolHandler> handlerMap自动注入所有底层组件(Spring会把同类型Bean按名称存入Map)。 - 工厂方法
createAdapter(String systemType)根据类型从Map中取出对应底层组件,和通用组件组合成完整适配器实例。 - 这种方式比构建器轻量得多,通用组件无需每次创建新实例,工厂只负责拼接差异化部分,逻辑清晰且维护成本低。
3. 借助Spring自动装配简化层级依赖选择
Spring的几个特性可以帮你在代码向下推进时自动匹配子依赖:
- 自定义注解+Spring EL:给底层组件标记
@AdapterType("PROTOCOL_V2"),在通用组件中通过@Autowired @AdapterType("#{externalSystemType}")动态注入对应实现(结合配置属性或上下文参数)。 - 条件化装配:用
@ConditionalOnProperty或自定义Condition,根据配置文件中的系统类型自动装配对应底层组件,适合单实例场景(比如系统只对接一种外部系统变体)。 - Bean名称映射:给底层组件命名为对应的类型标识(如
v1ProtocolHandler),通过Map注入后直接用key取值,省去手动遍历匹配的麻烦。
4. 不建议移除Adapter Factory让适配器自身决策
如果让适配器全权处理判定逻辑,会带来三个问题:
- 适配器类违背单一职责,既要处理业务逻辑又要做类型判断,代码臃肿难以维护。
- 差异化逻辑分散在各个层级,新增变体时需要修改多个类,违反开闭原则。
- 业务层直接依赖具体适配器实现,破坏封装性,无法做到对外部系统类型的完全隐藏。
示例代码片段
// 顶层适配器接口 public interface DataAdapter { List<Data> fetchData(); } // 通用中间层组件 @Service public class DefaultDataParser implements DataParser { private final ProtocolHandler protocolHandler; // 动态注入对应类型的ProtocolHandler public DefaultDataParser(@Autowired @AdapterType("${external.system.type}") ProtocolHandler protocolHandler) { this.protocolHandler = protocolHandler; } @Override public List<Data> parse(String rawData) { // 通用解析逻辑,调用底层handler处理差异化部分 String processed = protocolHandler.process(rawData); // ... 通用转换逻辑 return convertedData; } } // 底层差异化组件 @Component("PROTOCOL_V1") @AdapterType("PROTOCOL_V1") public class V1ProtocolHandler implements ProtocolHandler { @Override public String process(String rawData) { // V1协议的特殊处理逻辑 return processedRawData; } } // 工厂类 @Service public class AdapterFactory { private final Map<String, ProtocolHandler> handlerMap; private final DefaultDataParser dataParser; public AdapterFactory(Map<String, ProtocolHandler> handlerMap, DefaultDataParser dataParser) { this.handlerMap = handlerMap; this.dataParser = dataParser; } public DataAdapter createAdapter(String systemType) { ProtocolHandler handler = handlerMap.get(systemType); // 若通用组件需要替换handler,可通过构造器或Setter创建新实例 return new DefaultDataAdapter(dataParser, handler); } }
内容的提问来源于stack exchange,提问作者Florian
相关产品推荐
相关产品推荐

