设计模式手册008:适配器模式 - 让不兼容的接口协同工作
本文是「设计模式手册」系列第008篇,我们将深入探讨适配器模式,这种模式就像现实世界的电源适配器一样,让不兼容的接口能够协同工作,是系统集成和重构的利器。
1. 场景:我们为何需要适配器模式?
在软件开发中,我们经常遇到接口不兼容的问题:
- 新旧系统集成:新系统需要调用老系统的接口
- 第三方库集成:不同厂商提供的库接口不一致
- 数据格式转换:XML数据需要转换为JSON格式
- 协议适配:HTTP请求需要转换为gRPC调用
- 设备驱动:统一接口操作不同厂商的设备
现实困境的写照:
java
// 老系统的用户服务接口 - 已经稳定运行多年
public class LegacyUserService {
public String getUserInfoInXml(int userId) {
// 返回XML格式的用户信息
return "<user><id>" + userId + "</id><name>张三</name></user>";
}
public void updateUserInXml(String userXml) {
// 使用XML格式更新用户
System.out.println("更新用户: " + userXml);
}
}
// 新系统的用户接口 - 使用现代化的JSON格式
public interface ModernUserService {
User getUser(int userId);
void updateUser(User user);
}
// 新系统的用户对象
public class User {
private int id;
private String name;
private String email;
// 构造器、getter、setter...
public User(int id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
// getter和setter
public int getId() { return id; }
public String getName() { return name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
// 问题:新旧系统接口不兼容
public class NewSystem {
private ModernUserService userService;
public void processUser(int userId) {
// 新系统期望使用ModernUserService,但只有LegacyUserService可用
// User user = userService.getUser(userId); // 无法直接使用
// 临时解决方案:在每个使用的地方都写转换代码
LegacyUserService legacyService = new LegacyUserService();
String xmlData = legacyService.getUserInfoInXml(userId);
// 手动解析XML并转换为User对象
User user = parseXmlToUser(xmlData);
// 业务逻辑...
user.setEmail("new@email.com");
// 更新时又要转换回XML
String updatedXml = convertUserToXml(user);
legacyService.updateUserInXml(updatedXml);
}
// 重复的转换逻辑散布在各个地方
private User parseXmlToUser(String xml) {
// XML解析逻辑...
return new User(1, "张三", "zhangsan@email.com");
}
private String convertUserToXml(User user) {
// XML转换逻辑...
return "<user><id>" + user.getId() + "</id><name>" + user.getName() + "</name></user>";
}
}
这种实现的痛点:
- 代码重复:转换逻辑散布在各个地方
- 维护困难:接口变化时需要修改多处
- 违反开闭原则:每次集成新系统都要修改代码
- 业务逻辑污染:业务代码中混入适配逻辑
2. 适配器模式:定义与本质
2.1 模式定义
适配器模式(Adapter Pattern):将一个类的接口转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
2.2 核心角色
java
// 目标接口(Target):客户期望的接口
public interface ModernUserService {
User getUser(int userId);
void updateUser(User user);
}
// 被适配者(Adaptee):需要被适配的现有类
public class LegacyUserService {
public String getUserInfoInXml(int userId) {
return "<user><id>" + userId + "</id><name>张三</name><email>zhangsan@email.com</email></user>";
}
public void updateUserInXml(String userXml) {
System.out.println("Legacy系统更新用户: " + userXml);
}
}
// 适配器(Adapter):实现目标接口,包装被适配者
public class UserServiceAdapter implements ModernUserService {
private final LegacyUserService legacyService;
public UserServiceAdapter(LegacyUserService legacyService) {
this.legacyService = legacyService;
}
@Override
public User getUser(int userId) {
// 调用被适配者的方法,并进行转换
String xmlData = legacyService.getUserInfoInXml(userId);
return parseXmlToUser(xmlData);
}
@Override
public void updateUser(User user) {
String xmlData = convertUserToXml(user);
legacyService.updateUserInXml(xmlData);
}
private User parseXmlToUser(String xml) {
// 实际的XML解析逻辑
// 这里简化为模拟解析
System.out.println("解析XML: " + xml);
// 模拟从XML中提取数据
int id = extractIdFromXml(xml);
String name = extractNameFromXml(xml);
String email = extractEmailFromXml(xml);
return new User(id, name, email);
}
private String convertUserToXml(User user) {
return String.format("<user><id>%d</id><name>%s</name><email>%s</email></user>",
user.getId(), user.getName(), user.getEmail());
}
// 简化的XML解析方法
private int extractIdFromXml(String xml) {
// 实际应该使用DOM或SAX解析器
return 1; // 简化实现
}
private String extractNameFromXml(String xml) {
return "张三"; // 简化实现
}
private String extractEmailFromXml(String xml) {
return "zhangsan@email.com"; // 简化实现
}
}
3. 深入理解:适配器模式的多维视角
3.1 第一重:类适配器 vs 对象适配器
类适配器(通过继承)
java
// 类适配器:通过继承被适配者来实现
public class ClassUserServiceAdapter extends LegacyUserService implements ModernUserService {
@Override
public User getUser(int userId) {
String xmlData = getUserInfoInXml(userId);
return parseXmlToUser(xmlData);
}
@Override
public void updateUser(User user) {
String xmlData = convertUserToXml(user);
updateUserInXml(xmlData);
}
private User parseXmlToUser(String xml) {
// 解析逻辑...
return new User(1, "张三", "zhangsan@email.com");
}
private String convertUserToXml(User user) {
return String.format("<user><id>%d</id><name>%s</name></user>",
user.getId(), user.getName());
}
}
对象适配器(通过组合) - 推荐使用
java
// 对象适配器:通过组合被适配者来实现
public class ObjectUserServiceAdapter implements ModernUserService {
private final LegacyUserService legacyService;
public ObjectUserServiceAdapter(LegacyUserService legacyService) {
this.legacyService = legacyService;
}
@Override
public User getUser(int userId) {
String xmlData = legacyService.getUserInfoInXml(userId);
return parseXmlToUser(xmlData);
}
@Override
public void updateUser(User user) {
String xmlData = convertUserToXml(user);
legacyService.updateUserInXml(xmlData);
}
// 转换方法...
}
选择建议:
- 优先使用对象适配器(组合优于继承)
- 只有在必须重写被适配者行为时才考虑类适配器
3.2 第二重:双向适配器
java
// 双向适配器:可以在两个方向上进行适配
public class BidirectionalUserAdapter implements ModernUserService, LegacyUserInterface {
private final LegacyUserService legacyService;
private final ModernUserService modernService;
public BidirectionalUserAdapter(LegacyUserService legacyService, ModernUserService modernService) {
this.legacyService = legacyService;
this.modernService = modernService;
}
// 实现ModernUserService接口 - 新系统调用
@Override
public User getUser(int userId) {
String xmlData = legacyService.getUserInfoInXml(userId);
return parseXmlToUser(xmlData);
}
@Override
public void updateUser(User user) {
String xmlData = convertUserToXml(user);
legacyService.updateUserInXml(xmlData);
}
// 实现LegacyUserInterface接口 - 老系统调用
@Override
public String getLegacyUserInfo(int userId) {
User user = modernService.getUser(userId);
return convertUserToXml(user);
}
@Override
public void updateLegacyUser(String userXml) {
User user = parseXmlToUser(userXml);
modernService.updateUser(user);
}
// 转换方法...
}
3.3 第三重:适配器模式的变体
java
// 参数适配器:适配方法参数
public class PaymentParameterAdapter {
public static AlipayPaymentRequest adaptToAlipay(WechatPaymentRequest wechatRequest) {
return new AlipayPaymentRequest(
wechatRequest.getAmount(),
wechatRequest.getOrderId(),
wechatRequest.getSubject()
);
}
public static WechatPaymentRequest adaptToWechat(AlipayPaymentRequest alipayRequest) {
return new WechatPaymentRequest(
alipayRequest.getTotalAmount(),
alipayRequest.getOutTradeNo(),
alipayRequest.getSubject()
);
}
}
// 默认适配器:提供默认实现
public abstract class DefaultModernUserService implements ModernUserService {
@Override
public User getUser(int userId) {
throw new UnsupportedOperationException("getUser not implemented");
}
@Override
public void updateUser(User user) {
throw new UnsupportedOperationException("updateUser not implemented");
}
}
4. 实战案例:完整的多支付渠道集成
java
// 目标接口:统一的支付服务
public interface UnifiedPaymentService {
PaymentResult pay(PaymentRequest request);
PaymentResult query(String orderId);
boolean refund(RefundRequest request);
}
// 支付请求对象
@Data
public class PaymentRequest {
private String orderId;
private BigDecimal amount;
private String subject;
private String returnUrl;
private Map<String, String> extraParams;
}
// 支付结果
@Data
public class PaymentResult {
private boolean success;
private String message;
private String transactionId;
private String payUrl; // 用于二维码支付
private LocalDateTime payTime;
public static PaymentResult success(String transactionId, String payUrl) {
PaymentResult result = new PaymentResult();
result.setSuccess(true);
result.setTransactionId(transactionId);
result.setPayUrl(payUrl);
result.setPayTime(LocalDateTime.now());
return result;
}
public static PaymentResult failure(String message) {
PaymentResult result = new PaymentResult();
result.setSuccess(false);
result.setMessage(message);
return result;
}
}
// 支付宝支付服务 - 被适配者
public class AlipayService {
// 支付宝的原始接口
public AlipayResponse createOrder(AlipayOrder order) {
System.out.println("调用支付宝创建订单: " + order.getOutTradeNo());
// 模拟支付宝调用
AlipayResponse response = new AlipayResponse();
response.setSuccess(true);
response.setTradeNo("ALIPAY_" + System.currentTimeMillis());
response.setQrCode("https://qr.alipay.com/xxx");
return response;
}
public AlipayResponse queryOrder(String outTradeNo) {
System.out.println("调用支付宝查询订单: " + outTradeNo);
AlipayResponse response = new AlipayResponse();
response.setSuccess(true);
response.setTradeNo("ALIPAY_" + outTradeNo);
return response;
}
public boolean refundOrder(AlipayRefund refund) {
System.out.println("调用支付宝退款: " + refund.getOutTradeNo());
return true;
}
}
// 支付宝相关类
@Data
public class AlipayOrder {
private String outTradeNo;
private BigDecimal totalAmount;
private String subject;
private String returnUrl;
}
@Data
public class AlipayResponse {
private boolean success;
private String tradeNo;
private String qrCode;
private String message;
}
@Data
public class AlipayRefund {
private String outTradeNo;
private BigDecimal refundAmount;
private String refundReason;
}
// 微信支付服务 - 被适配者
public class WechatPayService {
// 微信支付的原始接口
public WechatPayResult unifiedOrder(WechatOrder order) {
System.out.println("调用微信统一下单: " + order.getOutTradeNo());
WechatPayResult result = new WechatPayResult();
result.setReturnCode("SUCCESS");
result.setResultCode("SUCCESS");
result.setPrepayId("WX_" + System.currentTimeMillis());
result.setCodeUrl("weixin://wxpay/xxx");
return result;
}
public WechatPayResult orderQuery(String outTradeNo) {
System.out.println("调用微信订单查询: " + outTradeNo);
WechatPayResult result = new WechatPayResult();
result.setReturnCode("SUCCESS");
result.setResultCode("SUCCESS");
result.setTransactionId("WX_" + outTradeNo);
return result;
}
public boolean refund(WechatRefund refund) {
System.out.println("调用微信退款: " + refund.getOutTradeNo());
return true;
}
}
// 微信支付相关类
@Data
public class WechatOrder {
private String outTradeNo;
private int totalFee; // 微信以分为单位
private String body;
private String notifyUrl;
}
@Data
public class WechatPayResult {
private String returnCode;
private String resultCode;
private String prepayId;
private String codeUrl;
private String transactionId;
}
@Data
public class WechatRefund {
private String outTradeNo;
private int refundFee;
private String refundDesc;
}
// 支付宝适配器
public class AlipayServiceAdapter implements UnifiedPaymentService {
private final AlipayService alipayService;
public AlipayServiceAdapter(AlipayService alipayService) {
this.alipayService = alipayService;
}
@Override
public PaymentResult pay(PaymentRequest request) {
// 将统一支付请求适配为支付宝订单
AlipayOrder order = new AlipayOrder();
order.setOutTradeNo(request.getOrderId());
order.setTotalAmount(request.getAmount());
order.setSubject(request.getSubject());
order.setReturnUrl(request.getReturnUrl());
// 调用支付宝服务
AlipayResponse response = alipayService.createOrder(order);
// 将支付宝响应适配为统一支付结果
if (response.isSuccess()) {
return PaymentResult.success(response.getTradeNo(), response.getQrCode());
} else {
return PaymentResult.failure(response.getMessage());
}
}
@Override
public PaymentResult query(String orderId) {
AlipayResponse response = alipayService.queryOrder(orderId);
if (response.isSuccess()) {
return PaymentResult.success(response.getTradeNo(), null);
} else {
return PaymentResult.failure(response.getMessage());
}
}
@Override
public boolean refund(RefundRequest request) {
AlipayRefund refund = new AlipayRefund();
refund.setOutTradeNo(request.getOrderId());
refund.setRefundAmount(request.getAmount());
refund.setRefundReason(request.getReason());
return alipayService.refundOrder(refund);
}
}
// 微信支付适配器
public class WechatPayServiceAdapter implements UnifiedPaymentService {
private final WechatPayService wechatPayService;
public WechatPayServiceAdapter(WechatPayService wechatPayService) {
this.wechatPayService = wechatPayService;
}
@Override
public PaymentResult pay(PaymentRequest request) {
// 将统一支付请求适配为微信订单
WechatOrder order = new WechatOrder();
order.setOutTradeNo(request.getOrderId());
order.setTotalFee(request.getAmount().multiply(BigDecimal.valueOf(100)).intValue()); // 元转分
order.setBody(request.getSubject());
order.setNotifyUrl(request.getReturnUrl());
// 调用微信支付服务
WechatPayResult result = wechatPayService.unifiedOrder(order);
// 将微信支付结果适配为统一支付结果
if ("SUCCESS".equals(result.getReturnCode()) && "SUCCESS".equals(result.getResultCode())) {
return PaymentResult.success(result.getPrepayId(), result.getCodeUrl());
} else {
return PaymentResult.failure("微信支付失败");
}
}
@Override
public PaymentResult query(String orderId) {
WechatPayResult result = wechatPayService.orderQuery(orderId);
if ("SUCCESS".equals(result.getReturnCode()) && "SUCCESS".equals(result.getResultCode())) {
return PaymentResult.success(result.getTransactionId(), null);
} else {
return PaymentResult.failure("微信查询失败");
}
}
@Override
public boolean refund(RefundRequest request) {
WechatRefund refund = new WechatRefund();
refund.setOutTradeNo(request.getOrderId());
refund.setRefundFee(request.getAmount().multiply(BigDecimal.valueOf(100)).intValue());
refund.setRefundDesc(request.getReason());
return wechatPayService.refund(refund);
}
}
// 退款请求
@Data
public class RefundRequest {
private String orderId;
private BigDecimal amount;
private String reason;
}
5. Spring框架中的适配器模式
Spring框架中大量使用了适配器模式:
5.1 Spring MVC中的HandlerAdapter
java
// 模拟Spring MVC的HandlerAdapter
public interface HandlerAdapter {
boolean supports(Object handler);
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
// Controller接口的适配器
@Component
public class ControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return handler instanceof Controller;
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
}
// 注解Controller的适配器
@Component
public class AnnotationMethodHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return handler instanceof HandlerMethod;
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 通过反射调用注解方法
Object result = invokeHandlerMethod(handlerMethod, request, response);
return adaptToModelAndView(result);
}
private Object invokeHandlerMethod(HandlerMethod handlerMethod, HttpServletRequest request, HttpServletResponse response) {
// 反射调用逻辑
try {
return handlerMethod.getMethod().invoke(
handlerMethod.getBean(), request, response
);
} catch (Exception e) {
throw new RuntimeException("调用处理器方法失败", e);
}
}
private ModelAndView adaptToModelAndView(Object result) {
if (result instanceof ModelAndView) {
return (ModelAndView) result;
} else if (result instanceof String) {
return new ModelAndView((String) result);
} else {
// 其他类型的适配逻辑
return new ModelAndView().addObject("result", result);
}
}
}
// 使用适配器的DispatcherServlet
@Component
public class DispatcherServlet {
private List<HandlerAdapter> handlerAdapters;
@Autowired
public DispatcherServlet(List<HandlerAdapter> handlerAdapters) {
this.handlerAdapters = handlerAdapters;
}
public void doDispatch(HttpServletRequest request, HttpServletResponse response) {
// 获取处理器
Object handler = getHandler(request);
// 获取适配器
HandlerAdapter adapter = getHandlerAdapter(handler);
// 通过适配器调用处理器
ModelAndView mv = adapter.handle(request, response, handler);
// 渲染视图
render(mv, request, response);
}
private HandlerAdapter getHandlerAdapter(Object handler) {
for (HandlerAdapter adapter : handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
throw new RuntimeException("没有找到支持的HandlerAdapter: " + handler.getClass());
}
private Object getHandler(HttpServletRequest request) {
// 根据请求找到对应的处理器
return new SomeController();
}
private void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) {
// 视图渲染逻辑
}
}
5.2 Spring Security的认证适配器
java
// 统一的认证接口
public interface AuthenticationProvider {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
boolean supports(Class<?> authentication);
}
// LDAP认证适配器
@Component
public class LdapAuthenticationProvider implements AuthenticationProvider {
private final LdapTemplate ldapTemplate;
public LdapAuthenticationProvider(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
// 调用LDAP服务进行认证
boolean authenticated = authenticateWithLdap(username, password);
if (authenticated) {
List<GrantedAuthority> authorities = getAuthoritiesFromLdap(username);
return new UsernamePasswordAuthenticationToken(username, password, authorities);
} else {
throw new BadCredentialsException("LDAP认证失败");
}
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
private boolean authenticateWithLdap(String username, String password) {
// LDAP认证逻辑
return ldapTemplate.authenticate("", "(uid=" + username + ")", password);
}
private List<GrantedAuthority> getAuthoritiesFromLdap(String username) {
// 从LDAP获取用户权限
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
}
}
6. 适配器模式的进阶用法
6.1 可配置的通用适配器
java
// 通用数据转换适配器
public class GenericDataAdapter<S, T> {
private final Function<S, T> transformFunction;
private final Function<T, S> reverseTransformFunction;
public GenericDataAdapter(Function<S, T> transformFunction, Function<T, S> reverseTransformFunction) {
this.transformFunction = transformFunction;
this.reverseTransformFunction = reverseTransformFunction;
}
public T adapt(S source) {
return transformFunction.apply(source);
}
public S reverseAdapt(T target) {
return reverseTransformFunction.apply(target);
}
// 批量适配
public List<T> adaptAll(List<S> sources) {
return sources.stream()
.map(this::adapt)
.collect(Collectors.toList());
}
// 创建常用的适配器
public static GenericDataAdapter<String, Integer> stringToIntegerAdapter() {
return new GenericDataAdapter<>(
Integer::parseInt,
Object::toString
);
}
public static GenericDataAdapter<Date, String> dateToStringAdapter(DateFormat format) {
return new GenericDataAdapter<>(
format::format,
str -> {
try {
return format.parse(str);
} catch (ParseException e) {
throw new RuntimeException("日期解析失败", e);
}
}
);
}
}
// 使用通用适配器
public class GenericAdapterExample {
public static void main(String[] args) {
// 字符串到整数的适配器
GenericDataAdapter<String, Integer> stringToIntAdapter = GenericDataAdapter.stringToIntegerAdapter();
int number = stringToIntAdapter.adapt("123");
System.out.println("转换结果: " + number);
String original = stringToIntAdapter.reverseAdapt(456);
System.out.println("反向转换: " + original);
// 批量转换
List<String> stringNumbers = Arrays.asList("1", "2", "3", "4", "5");
List<Integer> integers = stringToIntAdapter.adaptAll(stringNumbers);
System.out.println("批量转换: " + integers);
}
}
6.2 自动注册的适配器工厂
java
// 适配器注册表
@Component
public class AdapterRegistry {
private final Map<ClassPair, Object> adapters = new ConcurrentHashMap<>();
@SuppressWarnings("unchecked")
public <S, T> GenericDataAdapter<S, T> getAdapter(Class<S> sourceType, Class<T> targetType) {
ClassPair key = new ClassPair(sourceType, targetType);
return (GenericDataAdapter<S, T>) adapters.get(key);
}
public <S, T> void registerAdapter(Class<S> sourceType, Class<T> targetType, GenericDataAdapter<S, T> adapter) {
ClassPair key = new ClassPair(sourceType, targetType);
adapters.put(key, adapter);
}
public boolean supports(Class<?> sourceType, Class<?> targetType) {
return adapters.containsKey(new ClassPair(sourceType, targetType));
}
// 类对键
private static class ClassPair {
private final Class<?> source;
private final Class<?> target;
public ClassPair(Class<?> source, Class<?> target) {
this.source = source;
this.target = target;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ClassPair classPair = (ClassPair) o;
return Objects.equals(source, classPair.source) &&
Objects.equals(target, classPair.target);
}
@Override
public int hashCode() {
return Objects.hash(source, target);
}
}
}
// 自动配置适配器
@Configuration
public class AdapterAutoConfiguration {
@Bean
public AdapterRegistry adapterRegistry() {
AdapterRegistry registry = new AdapterRegistry();
// 注册常用适配器
registry.registerAdapter(String.class, Integer.class,
GenericDataAdapter.stringToIntegerAdapter());
registry.registerAdapter(Date.class, String.class,
GenericDataAdapter.dateToStringAdapter(new SimpleDateFormat("yyyy-MM-dd")));
return registry;
}
}
// 适配器服务
@Service
public class AdapterService {
private final AdapterRegistry adapterRegistry;
public AdapterService(AdapterRegistry adapterRegistry) {
this.adapterRegistry = adapterRegistry;
}
@SuppressWarnings("unchecked")
public <S, T> T adapt(S source, Class<T> targetType) {
Class<S> sourceType = (Class<S>) source.getClass();
GenericDataAdapter<S, T> adapter = adapterRegistry.getAdapter(sourceType, targetType);
if (adapter == null) {
throw new IllegalArgumentException("没有找到从 " + sourceType + " 到 " + targetType + " 的适配器");
}
return adapter.adapt(source);
}
public <S, T> List<T> adaptAll(List<S> sources, Class<T> targetType) {
if (sources.isEmpty()) {
return Collections.emptyList();
}
Class<S> sourceType = (Class<S>) sources.get(0).getClass();
GenericDataAdapter<S, T> adapter = adapterRegistry.getAdapter(sourceType, targetType);
if (adapter == null) {
throw new IllegalArgumentException("没有找到从 " + sourceType + " 到 " + targetType + " 的适配器");
}
return adapter.adaptAll(sources);
}
}
7. 适配器模式 vs 其他模式
7.1 适配器模式 vs 装饰器模式
- 适配器模式:改变接口,让不兼容的接口能够协同工作
- 装饰器模式:不改变接口,增强现有对象的功能
7.2 适配器模式 vs 外观模式
- 适配器模式:主要解决接口不兼容问题
- 外观模式:主要简化复杂系统的接口
7.3 适配器模式 vs 桥接模式
- 适配器模式:事后补救,让已有类能够协同工作
- 桥接模式:事前设计,将抽象和实现分离
8. 总结与思考
8.1 适配器模式的优点
- 解耦:将接口转换逻辑与业务逻辑分离
- 复用:让不兼容的类能够协同工作
- 灵活:可以适配多个不同的接口
- 符合开闭原则:新增适配器无需修改现有代码
8.2 适配器模式的缺点
- 复杂性增加:系统中增加了许多适配器类
- 性能开销:额外的转换层可能影响性能
- 调试困难:调用链变长,调试更复杂
- 过度设计:简单场景下可能过度设计
8.3 设计思考
适配器模式的本质是**"接口转换"**。它通过引入一个中间层来解决接口不兼容的问题,让原本无法协同工作的类能够一起工作。
深入思考的角度:
"适配器模式的核心价值在于它提供了一种在不修改现有代码的情况下集成不同系统的方法。它就像软件世界中的翻译官,让说不同'语言'的系统能够相互理解。"
在实际应用中,适配器模式有很多优秀的实践:
- Java中的Arrays.asList()方法
- InputStream和OutputStream的适配器
- Spring框架中的各种HandlerAdapter
- JDBC驱动就是数据库的适配器
从系统设计的角度看,适配器模式是开闭原则的完美体现。当需要集成新系统或第三方库时,我们不需要修改现有代码,只需要添加新的适配器即可。
最佳实践建议:
- 优先使用对象适配器(组合优于继承)
- 保持适配器的单一职责,只负责接口转换
- 考虑使用泛型创建通用适配器
- 为适配器编写充分的测试
- 在适配器中添加适当的日志和监控
使用场景判断:
- 适合:集成第三方库、新旧系统兼容、接口标准化
- 不适合:接口设计阶段(应该直接设计统一接口)、简单的一次性转换
下一篇预告:设计模式手册009 - 桥接模式:如何将抽象与实现分离,让它们可以独立变化?
版权声明:本文为CSDN博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。