文章目录
-
- 什么是适配器模式?
- 核心思想
- 模式结构
- 适配器模式的两种实现方式
-
- [1. 类适配器(通过继承实现)](#1. 类适配器(通过继承实现))
- [2. 对象适配器(通过组合实现)](#2. 对象适配器(通过组合实现))
- 完整示例:支付系统适配器
-
- [1. 支付系统基础结构](#1. 支付系统基础结构)
- [2. 第三方支付服务(适配者)](#2. 第三方支付服务(适配者))
- [3. 支付适配器实现](#3. 支付适配器实现)
- [4. 支付网关(客户端)](#4. 支付网关(客户端))
- [5. 客户端使用示例](#5. 客户端使用示例)
- 适配器模式的优点
-
- [1. 解决接口不兼容问题](#1. 解决接口不兼容问题)
- [2. 符合开闭原则](#2. 符合开闭原则)
- [3. 复用现有类](#3. 复用现有类)
- 适配器模式的缺点
-
- [1. 增加系统复杂度](#1. 增加系统复杂度)
- [2. 可能降低性能](#2. 可能降低性能)
- 适用场景
- 最佳实践
-
- [1. 合理选择适配器类型](#1. 合理选择适配器类型)
- [2. 保持适配器简单](#2. 保持适配器简单)
- [3. 使用依赖注入](#3. 使用依赖注入)
- 总结
什么是适配器模式?
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许不兼容的接口之间进行协作。适配器模式充当两个不兼容接口之间的桥梁,将一个类的接口转换成客户端期望的另一个接口。
核心思想
适配器模式的核心思想是:将一个类的接口转换成客户期望的另一个接口,使原本接口不兼容的类可以一起工作。 它就像现实世界中的电源适配器,让不同标准的插头能够插入同一个插座。
模式结构
适配器模式包含三个核心角色:
- 目标接口(Target):客户端期望使用的接口
- 适配者(Adaptee):需要被适配的现有接口
- 适配器(Adapter):将适配者接口转换成目标接口
适配器模式的两种实现方式
1. 类适配器(通过继承实现)
java
/**
* 目标接口 - 客户端期望的接口
* 定义客户端需要使用的标准方法
*/
public interface MediaPlayer {
/**
* 播放媒体文件
* @param audioType 音频类型
* @param fileName 文件名
*/
void play(String audioType, String fileName);
/**
* 获取支持的格式
* @return 支持的格式列表
*/
List<String> getSupportedFormats();
}
/**
* 适配者类 - 需要被适配的现有类
* 提供高级媒体播放功能,但接口不兼容
*/
public class AdvancedMediaPlayer {
private static final Set<String> SUPPORTED_FORMATS =
Set.of("mp4", "vlc", "avi", "mkv");
/**
* 播放视频文件 - 方法名和参数与目标接口不同
* @param videoFile 视频文件路径
* @param format 视频格式
*/
public void playVideo(String videoFile, String format) {
if (!SUPPORTED_FORMATS.contains(format.toLowerCase())) {
throw new IllegalArgumentException("不支持的视频格式: " + format);
}
System.out.println("播放视频: " + videoFile + " [格式: " + format + "]");
}
/**
* 获取高级播放器支持的格式
* @return 支持的格式集合
*/
public Set<String> getAdvancedFormats() {
return new HashSet<>(SUPPORTED_FORMATS);
}
/**
* 显示播放器信息
*/
public void displayPlayerInfo() {
System.out.println("高级媒体播放器 - 支持格式: " + SUPPORTED_FORMATS);
}
}
/**
* 类适配器 - 通过继承实现适配
* 继承适配者并实现目标接口
*/
public class MediaAdapter extends AdvancedMediaPlayer implements MediaPlayer {
@Override
public void play(String audioType, String fileName) {
// 将目标接口的方法调用适配到适配者的方法
System.out.println("媒体适配器: 转换播放请求");
playVideo(fileName, audioType);
}
@Override
public List<String> getSupportedFormats() {
// 将适配者的格式集合转换为目标接口期望的列表
return new ArrayList<>(getAdvancedFormats());
}
}
2. 对象适配器(通过组合实现)
java
/**
* 另一个适配者类 - 音频播放器
*/
public class AudioPlayer {
private static final Set<String> SUPPORTED_AUDIO_FORMATS =
Set.of("mp3", "wav", "aac", "flac");
/**
* 播放音频文件
* @param audioFile 音频文件
*/
public void playAudio(String audioFile) {
String format = getFileExtension(audioFile);
if (!SUPPORTED_AUDIO_FORMATS.contains(format)) {
throw new IllegalArgumentException("不支持的音频格式: " + format);
}
System.out.println("播放音频: " + audioFile + " [格式: " + format + "]");
}
/**
* 获取音频播放器信息
*/
public String getPlayerInfo() {
return "音频播放器 - 支持格式: " + SUPPORTED_AUDIO_FORMATS;
}
/**
* 获取支持的音频格式
*/
public Set<String> getAudioFormats() {
return new HashSet<>(SUPPORTED_AUDIO_FORMATS);
}
private String getFileExtension(String fileName) {
int lastDot = fileName.lastIndexOf('.');
return lastDot > 0 ? fileName.substring(lastDot + 1).toLowerCase() : "";
}
}
/**
* 对象适配器 - 通过组合实现适配
* 持有适配者实例并实现目标接口
*/
public class AudioPlayerAdapter implements MediaPlayer {
// 组合适配者对象
private final AudioPlayer audioPlayer;
public AudioPlayerAdapter(AudioPlayer audioPlayer) {
this.audioPlayer = audioPlayer;
}
@Override
public void play(String audioType, String fileName) {
// 验证文件格式是否匹配
String fileExtension = getFileExtension(fileName);
if (!audioType.equalsIgnoreCase(fileExtension)) {
throw new IllegalArgumentException("文件格式与指定类型不匹配: " +
fileExtension + " vs " + audioType);
}
System.out.println("音频适配器: 转换播放请求");
// 调用适配者的方法
audioPlayer.playAudio(fileName);
}
@Override
public List<String> getSupportedFormats() {
return new ArrayList<>(audioPlayer.getAudioFormats());
}
private String getFileExtension(String fileName) {
int lastDot = fileName.lastIndexOf('.');
return lastDot > 0 ? fileName.substring(lastDot + 1).toLowerCase() : "";
}
}
完整示例:支付系统适配器
让我们通过一个完整的支付系统示例来深入理解适配器模式。
1. 支付系统基础结构
java
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;
/**
* 支付结果类
*/
public class PaymentResult {
private final String transactionId;
private final boolean success;
private final String message;
private final BigDecimal amount;
private final LocalDateTime timestamp;
public PaymentResult(String transactionId, boolean success,
String message, BigDecimal amount) {
this.transactionId = transactionId;
this.success = success;
this.message = message;
this.amount = amount;
this.timestamp = LocalDateTime.now();
}
// Getter方法
public String getTransactionId() { return transactionId; }
public boolean isSuccess() { return success; }
public String getMessage() { return message; }
public BigDecimal getAmount() { return amount; }
public LocalDateTime getTimestamp() { return timestamp; }
@Override
public String toString() {
return String.format("支付结果[%s]: %s - %s (金额: ¥%.2f, 时间: %s)",
transactionId, success ? "成功" : "失败", message,
amount, timestamp.toString());
}
}
/**
* 目标接口 - 统一支付接口
* 定义标准的支付方法
*/
public interface UnifiedPayment {
/**
* 支付方法
* @param amount 支付金额
* @param orderId 订单ID
* @return 支付结果
*/
PaymentResult pay(BigDecimal amount, String orderId);
/**
* 退款方法
* @param transactionId 交易ID
* @param amount 退款金额
* @return 退款结果
*/
PaymentResult refund(String transactionId, BigDecimal amount);
/**
* 查询支付状态
* @param transactionId 交易ID
* @return 支付状态
*/
String queryPaymentStatus(String transactionId);
/**
* 获取支付方式名称
* @return 支付方式名称
*/
String getPaymentMethodName();
}
2. 第三方支付服务(适配者)
java
/**
* 支付宝支付服务 - 适配者1
* 第三方服务,接口与我们的系统不兼容
*/
public class AlipayService {
private static final String VERSION = "1.0";
/**
* 支付宝的支付方法 - 方法签名不同
* @param totalAmount 总金额(单位:分)
* @param outTradeNo 商户订单号
* @param subject 订单标题
* @return 支付宝返回的字符串结果
*/
public String alipayTradePay(int totalAmount, String outTradeNo, String subject) {
System.out.printf("调用支付宝支付: 订单%s, 金额%d分, 商品%s%n",
outTradeNo, totalAmount, subject);
// 模拟支付宝处理逻辑
try {
Thread.sleep(100); // 模拟网络延迟
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 模拟返回支付宝格式的响应
return "SUCCESS|" + UUID.randomUUID() + "|" + outTradeNo;
}
/**
* 支付宝退款方法 - 方法签名不同
* @param tradeNo 支付宝交易号
* @param refundAmount 退款金额(单位:分)
* @param outRequestNo 退款请求号
* @return 支付宝退款结果
*/
public String alipayTradeRefund(String tradeNo, int refundAmount, String outRequestNo) {
System.out.printf("调用支付宝退款: 交易号%s, 退款%d分, 请求号%s%n",
tradeNo, refundAmount, outRequestNo);
return "REFUND_SUCCESS|" + tradeNo + "|" + refundAmount;
}
/**
* 查询支付宝订单状态
* @param tradeNo 交易号
* @return 订单状态
*/
public String queryAlipayOrder(String tradeNo) {
System.out.println("查询支付宝订单状态: " + tradeNo);
return Math.random() > 0.1 ? "TRADE_SUCCESS" : "TRADE_CLOSED";
}
/**
* 获取支付宝服务信息
*/
public String getServiceInfo() {
return "支付宝支付服务 v" + VERSION;
}
}
/**
* 微信支付服务 - 适配者2
* 另一个第三方服务,接口同样不兼容
*/
public class WechatPayService {
private static final String APP_ID = "wx1234567890abcdef";
/**
* 微信统一下单接口 - 方法签名不同
* @param totalFee 总金额(单位:分)
* @param outTradeNo 商户订单号
* @param body 商品描述
* @return 微信支付预处理结果
*/
public Map<String, String> unifiedOrder(int totalFee, String outTradeNo, String body) {
System.out.printf("调用微信支付下单: 订单%s, 金额%d分, 描述%s%n",
outTradeNo, totalFee, body);
Map<String, String> result = new HashMap<>();
result.put("return_code", "SUCCESS");
result.put("result_code", "SUCCESS");
result.put("prepay_id", "wx" + System.currentTimeMillis());
result.put("out_trade_no", outTradeNo);
return result;
}
/**
* 微信退款接口
* @param transactionId 微信订单号
* @param outRefundNo 商户退款单号
* @param totalFee 订单金额
* @param refundFee 退款金额
* @return 退款结果
*/
public Map<String, String> refund(String transactionId, String outRefundNo,
int totalFee, int refundFee) {
System.out.printf("调用微信退款: 订单号%s, 退款%d/%d分%n",
transactionId, refundFee, totalFee);
Map<String, String> result = new HashMap<>();
result.put("return_code", "SUCCESS");
result.put("result_code", "SUCCESS");
result.put("refund_id", "wx_refund_" + System.currentTimeMillis());
return result;
}
/**
* 查询微信支付订单
* @param transactionId 交易号
* @return 订单信息
*/
public Map<String, String> orderQuery(String transactionId) {
System.out.println("查询微信支付订单: " + transactionId);
Map<String, String> result = new HashMap<>();
result.put("return_code", "SUCCESS");
result.put("trade_state", Math.random() > 0.1 ? "SUCCESS" : "REFUND");
return result;
}
/**
* 获取微信支付配置
*/
public String getConfig() {
return "微信支付 - AppID: " + APP_ID;
}
}
/**
* 银联支付服务 - 适配者3
*/
public class UnionPayService {
/**
* 银联支付接口
* @param orderAmount 订单金额(单位:元)
* @param orderNumber 订单号
* @param merchantId 商户号
* @return 银联支付结果
*/
public boolean unionPay(double orderAmount, String orderNumber, String merchantId) {
System.out.printf("调用银联支付: 订单%s, 金额%.2f元, 商户%s%n",
orderNumber, orderAmount, merchantId);
// 模拟银联支付处理
return Math.random() > 0.05; // 95%成功率
}
/**
* 银联退款接口
* @param originalOrderNumber 原订单号
* @param refundAmount 退款金额
* @param merchantId 商户号
* @return 退款是否成功
*/
public boolean unionRefund(String originalOrderNumber, double refundAmount, String merchantId) {
System.out.printf("调用银联退款: 原订单%s, 退款%.2f元%n",
originalOrderNumber, refundAmount);
return Math.random() > 0.1; // 90%成功率
}
/**
* 查询交易状态
* @param orderNumber 订单号
* @return 交易状态码
*/
public int queryTransactionStatus(String orderNumber) {
System.out.println("查询银联交易状态: " + orderNumber);
return Math.random() > 0.2 ? 100 : 200; // 100-成功, 200-失败
}
}
3. 支付适配器实现
java
/**
* 支付宝支付适配器 - 对象适配器
*/
public class AlipayAdapter implements UnifiedPayment {
private final AlipayService alipayService;
private final String merchantId;
public AlipayAdapter(AlipayService alipayService, String merchantId) {
this.alipayService = alipayService;
this.merchantId = merchantId;
}
@Override
public PaymentResult pay(BigDecimal amount, String orderId) {
System.out.println("支付宝适配器: 转换支付请求");
// 金额转换:元 -> 分
int amountInFen = amount.multiply(new BigDecimal("100")).intValue();
// 调用支付宝服务
String response = alipayService.alipayTradePay(
amountInFen, orderId, "商品购买");
// 解析支付宝响应并转换为统一格式
return parseAlipayResponse(response, amount, orderId);
}
@Override
public PaymentResult refund(String transactionId, BigDecimal amount) {
System.out.println("支付宝适配器: 转换退款请求");
int refundAmountInFen = amount.multiply(new BigDecimal("100")).intValue();
String refundRequestNo = "refund_" + System.currentTimeMillis();
String response = alipayService.alipayTradeRefund(
transactionId, refundAmountInFen, refundRequestNo);
return parseAlipayRefundResponse(response, amount, transactionId);
}
@Override
public String queryPaymentStatus(String transactionId) {
String status = alipayService.queryAlipayOrder(transactionId);
// 转换支付宝状态到统一状态
switch (status) {
case "TRADE_SUCCESS": return "SUCCESS";
case "TRADE_CLOSED": return "CLOSED";
default: return "UNKNOWN";
}
}
@Override
public String getPaymentMethodName() {
return "支付宝支付";
}
private PaymentResult parseAlipayResponse(String response, BigDecimal amount, String orderId) {
String[] parts = response.split("\\|");
boolean success = "SUCCESS".equals(parts[0]);
String transactionId = parts[1];
return new PaymentResult(
transactionId,
success,
success ? "支付宝支付成功" : "支付宝支付失败",
amount
);
}
private PaymentResult parseAlipayRefundResponse(String response, BigDecimal amount, String transactionId) {
String[] parts = response.split("\\|");
boolean success = "REFUND_SUCCESS".equals(parts[0]);
return new PaymentResult(
transactionId,
success,
success ? "支付宝退款成功" : "支付宝退款失败",
amount.negate() // 退款金额为负
);
}
}
/**
* 微信支付适配器
*/
public class WechatPayAdapter implements UnifiedPayment {
private final WechatPayService wechatPayService;
private final String appId;
public WechatPayAdapter(WechatPayService wechatPayService, String appId) {
this.wechatPayService = wechatPayService;
this.appId = appId;
}
@Override
public PaymentResult pay(BigDecimal amount, String orderId) {
System.out.println("微信支付适配器: 转换支付请求");
int amountInFen = amount.multiply(new BigDecimal("100")).intValue();
Map<String, String> result = wechatPayService.unifiedOrder(
amountInFen, orderId, "商品购买");
return parseWechatPayResponse(result, amount, orderId);
}
@Override
public PaymentResult refund(String transactionId, BigDecimal amount) {
System.out.println("微信支付适配器: 转换退款请求");
int refundAmountInFen = amount.multiply(new BigDecimal("100")).intValue();
String outRefundNo = "wx_refund_" + System.currentTimeMillis();
// 假设原订单金额为退款金额的2倍(简化处理)
int totalFee = refundAmountInFen * 2;
Map<String, String> result = wechatPayService.refund(
transactionId, outRefundNo, totalFee, refundAmountInFen);
return parseWechatRefundResponse(result, amount, transactionId);
}
@Override
public String queryPaymentStatus(String transactionId) {
Map<String, String> result = wechatPayService.orderQuery(transactionId);
String tradeState = result.get("trade_state");
switch (tradeState) {
case "SUCCESS": return "SUCCESS";
case "REFUND": return "REFUNDED";
default: return "UNKNOWN";
}
}
@Override
public String getPaymentMethodName() {
return "微信支付";
}
private PaymentResult parseWechatPayResponse(Map<String, String> result,
BigDecimal amount, String orderId) {
boolean success = "SUCCESS".equals(result.get("return_code"))
&& "SUCCESS".equals(result.get("result_code"));
String transactionId = success ? result.get("prepay_id") : "FAILED";
return new PaymentResult(
transactionId,
success,
success ? "微信支付下单成功" : "微信支付下单失败",
amount
);
}
private PaymentResult parseWechatRefundResponse(Map<String, String> result,
BigDecimal amount, String transactionId) {
boolean success = "SUCCESS".equals(result.get("return_code"))
&& "SUCCESS".equals(result.get("result_code"));
return new PaymentResult(
transactionId,
success,
success ? "微信退款成功" : "微信退款失败",
amount.negate()
);
}
}
/**
* 银联支付适配器
*/
public class UnionPayAdapter implements UnifiedPayment {
private final UnionPayService unionPayService;
private final String merchantId;
public UnionPayAdapter(UnionPayService unionPayService, String merchantId) {
this.unionPayService = unionPayService;
this.merchantId = merchantId;
}
@Override
public PaymentResult pay(BigDecimal amount, String orderId) {
System.out.println("银联支付适配器: 转换支付请求");
double amountYuan = amount.doubleValue();
boolean success = unionPayService.unionPay(amountYuan, orderId, merchantId);
String transactionId = success ? "union_" + System.currentTimeMillis() : "FAILED";
return new PaymentResult(
transactionId,
success,
success ? "银联支付成功" : "银联支付失败",
amount
);
}
@Override
public PaymentResult refund(String transactionId, BigDecimal amount) {
System.out.println("银联支付适配器: 转换退款请求");
// 从transactionId中提取原订单号(简化处理)
String originalOrderId = transactionId.replace("union_", "order_");
double refundAmountYuan = amount.doubleValue();
boolean success = unionPayService.unionRefund(originalOrderId, refundAmountYuan, merchantId);
return new PaymentResult(
transactionId,
success,
success ? "银联退款成功" : "银联退款失败",
amount.negate()
);
}
@Override
public String queryPaymentStatus(String transactionId) {
String orderId = transactionId.replace("union_", "order_");
int statusCode = unionPayService.queryTransactionStatus(orderId);
return statusCode == 100 ? "SUCCESS" : "FAILED";
}
@Override
public String getPaymentMethodName() {
return "银联支付";
}
}
4. 支付网关(客户端)
java
/**
* 支付网关 - 客户端代码
* 使用统一的支付接口,不需要关心具体支付实现的差异
*/
public class PaymentGateway {
private final Map<String, UnifiedPayment> paymentMethods;
public PaymentGateway() {
this.paymentMethods = new HashMap<>();
initializePaymentMethods();
}
/**
* 初始化所有支付方式
*/
private void initializePaymentMethods() {
// 初始化支付宝支付
AlipayService alipayService = new AlipayService();
UnifiedPayment alipayAdapter = new AlipayAdapter(alipayService, "2088xxxxx");
paymentMethods.put("alipay", alipayAdapter);
// 初始化微信支付
WechatPayService wechatPayService = new WechatPayService();
UnifiedPayment wechatPayAdapter = new WechatPayAdapter(wechatPayService, "wx123456789");
paymentMethods.put("wechat", wechatPayAdapter);
// 初始化银联支付
UnionPayService unionPayService = new UnionPayService();
UnifiedPayment unionPayAdapter = new UnionPayAdapter(unionPayService, "700000000000001");
paymentMethods.put("union", unionPayAdapter);
System.out.println("支付网关初始化完成,支持以下支付方式:");
paymentMethods.forEach((key, payment) ->
System.out.println(" - " + payment.getPaymentMethodName() + " (" + key + ")"));
}
/**
* 执行支付
* @param paymentMethod 支付方式
* @param amount 金额
* @param orderId 订单ID
* @return 支付结果
*/
public PaymentResult processPayment(String paymentMethod, BigDecimal amount, String orderId) {
UnifiedPayment payment = paymentMethods.get(paymentMethod.toLowerCase());
if (payment == null) {
throw new IllegalArgumentException("不支持的支付方式: " + paymentMethod);
}
System.out.printf("\n开始处理支付: %s订单, 金额¥%.2f, 方式%s%n",
orderId, amount, payment.getPaymentMethodName());
return payment.pay(amount, orderId);
}
/**
* 执行退款
* @param paymentMethod 支付方式
* @param transactionId 交易ID
* @param amount 退款金额
* @return 退款结果
*/
public PaymentResult processRefund(String paymentMethod, String transactionId, BigDecimal amount) {
UnifiedPayment payment = paymentMethods.get(paymentMethod.toLowerCase());
if (payment == null) {
throw new IllegalArgumentException("不支持的支付方式: " + paymentMethod);
}
System.out.printf("\n开始处理退款: 交易%s, 退款¥%.2f, 方式%s%n",
transactionId, amount, payment.getPaymentMethodName());
return payment.refund(transactionId, amount);
}
/**
* 查询支付状态
* @param paymentMethod 支付方式
* @param transactionId 交易ID
* @return 支付状态
*/
public String queryPaymentStatus(String paymentMethod, String transactionId) {
UnifiedPayment payment = paymentMethods.get(paymentMethod.toLowerCase());
if (payment == null) {
throw new IllegalArgumentException("不支持的支付方式: " + paymentMethod);
}
return payment.queryPaymentStatus(transactionId);
}
/**
* 获取支持的支付方式
*/
public Set<String> getSupportedPaymentMethods() {
return paymentMethods.keySet();
}
}
5. 客户端使用示例
java
/**
* 适配器模式客户端演示
*/
public class AdapterPatternDemo {
public static void main(String[] args) {
System.out.println("=== 适配器模式完整演示 - 支付系统 ===\n");
// 创建支付网关
PaymentGateway paymentGateway = new PaymentGateway();
// 演示1: 多种支付方式处理
demonstrateMultiplePayments(paymentGateway);
// 演示2: 退款处理
demonstrateRefunds(paymentGateway);
// 演示3: 状态查询
demonstrateStatusQuery(paymentGateway);
// 演示4: 媒体播放器示例
demonstrateMediaPlayer();
}
/**
* 演示多种支付方式
*/
private static void demonstrateMultiplePayments(PaymentGateway gateway) {
System.out.println("\n1. 多种支付方式演示:");
System.out.println("-".repeat(50));
BigDecimal amount = new BigDecimal("199.99");
String orderId = "ORDER_" + System.currentTimeMillis();
// 使用支付宝支付
PaymentResult alipayResult = gateway.processPayment("alipay", amount, orderId + "_1");
System.out.println(alipayResult);
// 使用微信支付
PaymentResult wechatResult = gateway.processPayment("wechat", amount, orderId + "_2");
System.out.println(wechatResult);
// 使用银联支付
PaymentResult unionResult = gateway.processPayment("union", amount, orderId + "_3");
System.out.println(unionResult);
}
/**
* 演示退款处理
*/
private static void demonstrateRefunds(PaymentGateway gateway) {
System.out.println("\n2. 退款处理演示:");
System.out.println("-".repeat(50));
BigDecimal refundAmount = new BigDecimal("50.00");
// 模拟退款
PaymentResult alipayRefund = gateway.processRefund("alipay", "mock_transaction_123", refundAmount);
System.out.println(alipayRefund);
PaymentResult wechatRefund = gateway.processRefund("wechat", "wx_mock_456", refundAmount);
System.out.println(wechatRefund);
}
/**
* 演示状态查询
*/
private static void demonstrateStatusQuery(PaymentGateway gateway) {
System.out.println("\n3. 支付状态查询演示:");
System.out.println("-".repeat(50));
String alipayStatus = gateway.queryPaymentStatus("alipay", "mock_transaction_123");
System.out.println("支付宝交易状态: " + alipayStatus);
String wechatStatus = gateway.queryPaymentStatus("wechat", "wx_mock_456");
System.out.println("微信交易状态: " + wechatStatus);
String unionStatus = gateway.queryPaymentStatus("union", "union_mock_789");
System.out.println("银联交易状态: " + unionStatus);
}
/**
* 演示媒体播放器
*/
private static void demonstrateMediaPlayer() {
System.out.println("\n4. 媒体播放器适配器演示:");
System.out.println("-".repeat(50));
// 创建适配器
MediaAdapter mediaAdapter = new MediaAdapter();
AudioPlayerAdapter audioAdapter = new AudioPlayerAdapter(new AudioPlayer());
// 使用适配器播放媒体
System.out.println("使用媒体适配器播放视频:");
mediaAdapter.play("mp4", "movie.mp4");
System.out.println("\n使用音频适配器播放音频:");
audioAdapter.play("mp3", "song.mp3");
// 显示支持的格式
System.out.println("\n媒体适配器支持格式: " + mediaAdapter.getSupportedFormats());
System.out.println("音频适配器支持格式: " + audioAdapter.getSupportedFormats());
}
}
适配器模式的优点
1. 解决接口不兼容问题
java
// 客户端使用统一的接口,不需要关心具体实现
UnifiedPayment payment = paymentGateway.getPayment("alipay");
PaymentResult result = payment.pay(amount, orderId);
// 无论底层是支付宝、微信还是银联,调用方式都一样
2. 符合开闭原则
java
// 新增支付方式时,只需要添加新的适配器
public class NewPaymentAdapter implements UnifiedPayment {
// 实现新的支付适配器,不需要修改现有代码
}
3. 复用现有类
java
// 可以复用现有的第三方库,即使接口不兼容
AlipayService alipay = new AlipayService(); // 现有类
UnifiedPayment adapter = new AlipayAdapter(alipay); // 通过适配器复用
适配器模式的缺点
1. 增加系统复杂度
java
// 需要额外的适配器类
public class AlipayAdapter implements UnifiedPayment {
// 每个不兼容的接口都需要一个适配器
}
2. 可能降低性能
java
// 适配器调用链增加
client -> adapter -> adaptee
// 多了一层调用,可能影响性能
适用场景
- 集成第三方库或遗留系统
- 统一多个类的接口
- 需要复用一些现有的类,但这些类的接口与系统要求不一致
- 想要创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作
最佳实践
1. 合理选择适配器类型
java
// 类适配器:当需要同时使用适配者的多个方法时
public class ClassAdapter extends Adaptee implements Target {
// 通过继承获得所有方法
}
// 对象适配器:当需要更灵活的组合时
public class ObjectAdapter implements Target {
private Adaptee adaptee; // 通过组合
}
2. 保持适配器简单
java
public class SimpleAdapter implements Target {
// 适配器应该只负责接口转换,不包含复杂业务逻辑
public void targetMethod() {
adaptee.adapteeMethod(); // 简单的委托
}
}
3. 使用依赖注入
java
public class PaymentGateway {
private final UnifiedPayment payment;
// 通过构造函数注入适配器
public PaymentGateway(UnifiedPayment payment) {
this.payment = payment;
}
}
总结
适配器模式是解决接口不兼容问题的利器,它在系统集成和代码复用中发挥着重要作用。
核心价值:
- 让不兼容的接口能够协同工作
- 提高代码的复用性
- 符合开闭原则,易于扩展
使用建议:
- 当需要集成第三方库时使用
- 当需要统一多个类似功能的接口时使用
- 当需要复用现有类但接口不匹配时使用
实现选择:
- 类适配器:适用于需要多重继承的场景(Java中不适用)
- 对象适配器:更灵活,推荐使用
掌握适配器模式能够帮助我们在复杂的系统集成中游刃有余,让不同的组件能够和谐地协同工作。