适配器模式

适配器模式(Adapter Pattern)

定义

适配器模式是一种结构型设计模式,它允许接口不兼容的类能够一起工作。适配器充当两个不兼容接口之间的桥梁,将一个类的接口转换成客户端期望的另一个接口。

核心思想

  • 接口转换:将一个接口转换成另一个客户端期望的接口

  • 兼容性桥梁:使原本不兼容的类可以协同工作

  • 复用已有类:不需要修改原有代码就能复用现有类

模式结构

Client(客户端)
│
Target(目标接口)
│
├── Adapter(适配器)
│     │
│     └── Adaptee(被适配者)
│
└── ConcreteTarget(具体目标)

关键组件:

  • Target:客户端期望使用的目标接口

  • Adaptee:需要被适配的已有类(不兼容的接口)

  • Adapter:适配器类,实现Target接口并包装Adaptee实例

  • Client:与符合Target接口的对象协同工作

主要解决的问题

  • 接口不兼容:已有类的接口不符合系统需求

  • 复用遗留代码:需要复用一些已经存在的类,但其接口与系统不匹配

  • 统一多个类接口:需要将多个不同接口的类统一为相同接口

代码示例

  • 场景描述
    假设有一个现有的第三方日志库(Adaptee),它的接口与我们的系统期望的日志接口(Target)不兼容,我们需要使用适配器使其兼容。
using System;

// 目标接口:系统期望的日志接口
public interface ILogger
{
    void Log(string message);
    void Error(string message);
    void Warn(string message);
}

// 被适配者:现有的第三方日志类(不兼容接口)
public class ThirdPartyLogger
{
    public void LogMessage(string message)
    {
        Console.WriteLine($"Log: {message}");
    }
    
    public void LogError(string error)
    {
        Console.WriteLine($"ERROR: {error}");
    }
    
    public void LogWarning(string warning)
    {
        Console.WriteLine($"WARN: {warning}");
    }
}

// 类适配器(通过继承实现)
public class LoggerClassAdapter : ThirdPartyLogger, ILogger
{
    public void Log(string message)
    {
        base.LogMessage(message);
    }
    
    public void Error(string message)
    {
        base.LogError(message);
    }
    
    public void Warn(string message)
    {
        base.LogWarning(message);
    }
}

// 对象适配器(通过组合实现)
public class LoggerObjectAdapter : ILogger
{
    private readonly ThirdPartyLogger _logger;
    
    public LoggerObjectAdapter(ThirdPartyLogger logger)
    {
        _logger = logger;
    }
    
    public void Log(string message)
    {
        _logger.LogMessage(message);
    }
    
    public void Error(string message)
    {
        _logger.LogError(message);
    }
    
    public void Warn(string message)
    {
        _logger.LogWarning(message);
    }
}

// 客户端代码
class Program
{
    static void Main(string[] args)
    {
        // 使用类适配器
        ILogger classAdapter = new LoggerClassAdapter();
        classAdapter.Log("类适配器测试消息");
        classAdapter.Error("类适配器测试错误");
        classAdapter.Warn("类适配器测试警告");
        
        Console.WriteLine();
        
        // 使用对象适配器
        ThirdPartyLogger thirdPartyLogger = new ThirdPartyLogger();
        ILogger objectAdapter = new LoggerObjectAdapter(thirdPartyLogger);
        objectAdapter.Log("对象适配器测试消息");
        objectAdapter.Error("对象适配器测试错误");
        objectAdapter.Warn("对象适配器测试警告");
        
        /* 输出:
        Log: 类适配器测试消息
        ERROR: 类适配器测试错误
        WARN: 类适配器测试警告
        
        Log: 对象适配器测试消息
        ERROR: 对象适配器测试错误
        WARN: 对象适配器测试警告
        */
    }
}

模式对比

模式 目的 关键区别
适配器 使不兼容接口能够一起工作 关注接口转换,事后补救
桥接 分离抽象与实现 事前设计,让抽象和实现独立变化
装饰器 动态添加职责 不改变接口,增强功能
外观 简化复杂子系统接口 定义新接口,不涉及接口转换

主要区别:

  • 适配器 vs 桥接:适配器是事后补救,桥接是事前设计

  • 适配器 vs 装饰器:适配器改变接口,装饰器保持接口

  • 适配器 vs 外观:适配器使已有类可用,外观简化复杂系统

总结

优点

  • 兼容性:使不兼容的接口能够协同工作

  • 复用性:可以复用现有的类而不需要修改其代码

  • 灵活性:可以同时适配多个被适配者

  • 开闭原则:引入适配器而不改变现有代码

缺点

  • 过度使用复杂性:过多使用适配器会使系统变得混乱

  • 性能开销:额外的间接调用会带来轻微性能损失

  • 设计警示:可能表明系统接口设计存在问题

适用场景

  • 需要使用现有类,但其接口不符合需求

  • 需要创建一个可复用的类,与不相关或不可预见的类协同工作

  • 需要统一多个不同子系统的接口

  • 需要为多个已有子类提供统一接口

适配器模式在以下情况特别有用:
  • 集成第三方库

  • 升级系统时保持与旧组件的兼容

  • 统一不同版本的API接口

  • 跨平台开发中处理平台特定API

最佳实践:
  • 优先使用对象适配器(组合),因为它更灵活,可以适配多个不同的被适配者,而类适配器(继承)在某些语言中受限于单继承的限制。
posted @ 2025-03-31 16:01  刘继先  阅读(22)  评论(0)    收藏  举报