
1. 适配器模式初探连接不兼容世界的桥梁在软件开发中我们经常会遇到这样的场景新系统需要与遗留系统对接或者第三方库的接口与我们的预期不符。就像旅行时带着欧标插头的电器来到英国面对形状迥异的插座我们需要一个转接头才能正常使用——这就是适配器模式Adapter Pattern在现实生活中的完美体现。作为结构型设计模式中的和事佬适配器模式的核心价值在于让原本由于接口不兼容而不能一起工作的类能够协同工作。它通过创建一个中间层来转换接口使得客户端可以以统一的方式调用不同接口的对象。这种模式在实际开发中应用极为广泛从数据库驱动到UI组件库从支付接口到日志系统几乎无处不在。2. 适配器模式的结构解析2.1 类适配器与对象适配器适配器模式主要有两种实现方式类适配器继承方式// 目标接口客户端期望的接口 interface Target { void request(); } // 被适配者需要适配的现有类 class Adaptee { public void specificRequest() { System.out.println(特殊请求处理); } } // 适配器通过继承实现 class ClassAdapter extends Adaptee implements Target { Override public void request() { specificRequest(); // 将目标接口转换为被适配者接口 } }对象适配器组合方式class ObjectAdapter implements Target { private Adaptee adaptee; public ObjectAdapter(Adaptee adaptee) { this.adaptee adaptee; } Override public void request() { adaptee.specificRequest(); } }两种实现方式的对比特性类适配器对象适配器实现方式继承被适配类组合被适配类对象灵活性较低静态关系较高运行时可替换适用场景适配单一类适配类及其子类代码耦合度较高较低提示现代编程更推荐使用对象适配器因为它遵循了组合优于继承的原则且能适配整个类层次结构。2.2 适配器模式的参与者角色Target目标接口客户端期望的接口定义了客户端需要使用的特定领域接口。Adaptee被适配者已经存在的接口需要被适配的类通常包含一些有用的功能。Adapter适配器对Adaptee的接口进行适配使其符合Target接口的要求。3. 适配器模式的典型应用场景3.1 遗留系统集成在系统升级过程中我们经常需要让新代码与遗留代码协同工作。例如公司原有的用户认证系统使用XML格式传输数据而新系统采用JSON格式// 旧系统接口 class LegacyAuthService { public String getUserInfoXml(String userId) { return useriduserId/idname张三/name/user; } } // 新系统期望的接口 interface ModernAuthService { JSONObject getUserInfoJson(String userId); } // 适配器实现 class AuthAdapter implements ModernAuthService { private LegacyAuthService legacyService; public AuthAdapter(LegacyAuthService service) { this.legacyService service; } Override public JSONObject getUserInfoJson(String userId) { String xml legacyService.getUserInfoXml(userId); return XML.toJSONObject(xml); // 转换XML到JSON } }3.2 第三方库适配不同日志框架的API差异很大使用适配器模式可以统一日志接口// 统一的日志接口 interface Logger { void log(String level, String message); } // Log4j适配器 class Log4jAdapter implements Logger { private org.apache.log4j.Logger log4j; public Log4jAdapter(Class? clazz) { this.log4j org.apache.log4j.Logger.getLogger(clazz); } Override public void log(String level, String message) { switch(level.toLowerCase()) { case debug: log4j.debug(message); break; case info: log4j.info(message); break; // 其他级别处理... } } }3.3 接口版本兼容当API升级导致接口不兼容时可以使用适配器保持向后兼容// 新版本接口 interface NewPaymentService { PaymentResult pay(String orderId, BigDecimal amount, PaymentMethod method); } // 旧版本适配器 class OldPaymentAdapter implements NewPaymentService { private OldPaymentService oldService; public PaymentResult pay(String orderId, BigDecimal amount, PaymentMethod method) { // 将新接口参数转换为旧接口格式 String oldMethod convertPaymentMethod(method); String result oldService.processPayment(orderId, amount.toString(), oldMethod); return parseOldResult(result); } // 转换方法省略... }4. 适配器模式的实现技巧与最佳实践4.1 实现注意事项接口最小化适配只适配真正需要的方法不要盲目实现整个接口。对于不需要的方法可以抛出UnsupportedOperationException。保持单一职责一个适配器应该只负责一个特定接口的转换避免创建万能适配器。考虑线程安全如果被适配对象不是线程安全的需要在适配器中添加同步机制。性能考量频繁调用的适配器可能需要考虑缓存策略避免重复转换开销。4.2 与其他模式的关系桥接模式都是连接不同部分的模式但桥接模式关注的是抽象和实现的分离而适配器关注的是接口转换。装饰器模式都可以包装对象但装饰器是为了增强功能适配器是为了转换接口。外观模式都是对复杂系统的简化但外观模式定义的是新接口适配器是复用现有接口。5. 实战案例支付网关统一适配假设我们需要集成多个支付渠道支付宝、微信、银联各渠道接口差异很大// 统一支付接口 interface UnifiedPayment { boolean pay(Order order); boolean refund(Order order); PaymentStatus checkStatus(String orderId); } // 支付宝适配器 class AlipayAdapter implements UnifiedPayment { private AlipayService alipay; public boolean pay(Order order) { AlipayRequest request new AlipayRequest(); request.setOutTradeNo(order.getId()); request.setTotalAmount(order.getAmount()); // 其他字段转换... AlipayResponse response alipay.tradePay(request); return response.isSuccess(); } // 其他方法实现... } // 微信支付适配器 class WechatpayAdapter implements UnifiedPayment { private WechatPayService wechatPay; public boolean pay(Order order) { WechatPayUnifiedOrderRequest request new WechatPayUnifiedOrderRequest(); request.setOutTradeNo(order.getId()); request.setTotalFee(order.getAmount().multiply(100).intValue()); // 其他字段转换... return wechatPay.unifiedOrder(request).isSuccess(); } // 其他方法实现... }在这个案例中适配器模式带来了以下优势业务代码只需面向统一的UnifiedPayment口编程新增支付渠道只需添加新的适配器不影响现有代码各支付渠道的特殊处理被封装在适配器中便于单元测试和模拟6. 适配器模式的局限性与替代方案虽然适配器模式非常实用但也有其局限性过度使用会导致系统复杂如果系统中适配器过多会使得代码难以理解和维护。性能开销额外的间接调用会带来一定的性能损耗对性能敏感的场景需要谨慎。设计警示如果需要大量使用适配器可能意味着系统接口设计存在问题。替代方案考虑如果可能直接修改接口使其保持一致使用外观模式提供更高级别的统一接口对于简单转换可以使用静态工具类方法我在实际项目中使用适配器模式的经验是对于短期集成方案或无法修改的第三方接口适配器是很好的解决方案但对于长期维护的核心系统应该考虑重构接口设计减少对适配器的依赖。