适配器模式
适配器模式(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
最佳实践:
- 优先使用对象适配器(组合),因为它更灵活,可以适配多个不同的被适配者,而类适配器(继承)在某些语言中受限于单继承的限制。

浙公网安备 33010602011771号