设计模式之:适配器模式

文章目录

    • 什么是适配器模式?
    • 核心思想
    • 模式结构
    • 适配器模式的两种实现方式
      • [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)是一种结构型设计模式,它允许不兼容的接口之间进行协作。适配器模式充当两个不兼容接口之间的桥梁,将一个类的接口转换成客户端期望的另一个接口。

核心思想

适配器模式的核心思想是:将一个类的接口转换成客户期望的另一个接口,使原本接口不兼容的类可以一起工作。 它就像现实世界中的电源适配器,让不同标准的插头能够插入同一个插座。

模式结构

适配器模式包含三个核心角色:

  1. 目标接口(Target):客户端期望使用的接口
  2. 适配者(Adaptee):需要被适配的现有接口
  3. 适配器(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. 集成第三方库或遗留系统
  2. 统一多个类的接口
  3. 需要复用一些现有的类,但这些类的接口与系统要求不一致
  4. 想要创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作

最佳实践

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中不适用)
  • 对象适配器:更灵活,推荐使用

掌握适配器模式能够帮助我们在复杂的系统集成中游刃有余,让不同的组件能够和谐地协同工作。

相关推荐
xiezhr6 小时前
见过哪些醍醐灌顶的Java代码:从"卧槽"到"原来如此"的顿悟
java·后端·设计模式
WaWaJie_Ngen6 小时前
【设计模式】适配器模式(Adapter)
设计模式·适配器模式
Mr_WangAndy17 小时前
C++设计模式_行为型模式_策略模式Strategy
c++·设计模式·策略模式·依赖倒置原则
LoveXming17 小时前
Chapter11—适配器模式
c++·设计模式·适配器模式·开闭原则
杯莫停丶18 小时前
设计模式之:单例模式
java·单例模式·设计模式
WaWaJie_Ngen20 小时前
【设计模式】工厂模式(Factory)
c++·设计模式·简单工厂模式·工厂方法模式·抽象工厂模式
YuanlongWang21 小时前
C# 设计模式——工厂模式
开发语言·设计模式·c#
消失的旧时光-194321 小时前
MQTT主题架构的艺术:从字符串拼接走向设计模式
设计模式
Code_Geo1 天前
agent设计模式:第三章节—并行化
java·设计模式·agent·并行化