适配器模式(Adapter Pattern) 是一种结构型设计模式,它允许将不兼容的接口转换为客户端期望的接口,使原本由于接口不兼容而不能一起工作的类可以协同工作。
一、核心思想
- 将一个类的接口转换成客户期望的另一个接口
- 使原本因接口不匹配而无法一起工作的类能够一起工作
- 属于"包装器"(Wrapper)设计模式的一种
二、适用场景
1.需要使用现有类,但其接口与需求不匹配
2.想要复用一些现有的子类,但这些子类缺少一些公共功能
3.需要与多个不兼容的接口或库一起工作
三、适配器模式在 C# 中的实现
1. 类适配器(使用继承)
csharp
// 目标接口(客户端期望的接口)
public interface ITarget
{
void Request();
}
// 被适配者(现有的不兼容类)
public class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Adaptee's SpecificRequest() called");
}
}
// 类适配器(通过多重继承实现)
public class ClassAdapter : Adaptee, ITarget
{
public void Request()
{
// 将目标接口方法转换为被适配者的方法
base.SpecificRequest();
}
}
// 客户端代码
class Program
{
static void Main()
{
ITarget target = new ClassAdapter();
target.Request(); // 输出: Adaptee's SpecificRequest() called
}
}
2. 对象适配器(使用组合)
csharp
// 目标接口
public interface ITarget
{
void Request();
}
// 被适配者
public class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Adaptee's SpecificRequest() called");
}
}
// 对象适配器(通过组合实现)
public class ObjectAdapter : ITarget
{
private readonly Adaptee _adaptee;
public ObjectAdapter(Adaptee adaptee)
{
_adaptee = adaptee;
}
public void Request()
{
// 将请求委托给被适配者
_adaptee.SpecificRequest();
}
}
// 客户端代码
class Program
{
static void Main()
{
Adaptee adaptee = new Adaptee();
ITarget target = new ObjectAdapter(adaptee);
target.Request(); // 输出: Adaptee's SpecificRequest() called
}
}
四、实际应用示例
示例:第三方支付系统适配
csharp
// 目标接口(系统期望的支付接口)
public interface IPaymentGateway
{
void ProcessPayment(decimal amount);
}
// 第三方支付系统(不兼容的接口)
public class ThirdPartyPaymentProcessor
{
public void MakePayment(double amount)
{
Console.WriteLine($"Processing payment of amount: {amount}");
}
}
// 适配器
public class PaymentAdapter : IPaymentGateway
{
private readonly ThirdPartyPaymentProcessor _processor;
public PaymentAdapter(ThirdPartyPaymentProcessor processor)
{
_processor = processor;
}
public void ProcessPayment(decimal amount)
{
// 将decimal转换为double以适应第三方系统
double convertedAmount = (double)amount;
_processor.MakePayment(convertedAmount);
}
}
// 客户端代码
class Program
{
static void Main()
{
var thirdPartyProcessor = new ThirdPartyPaymentProcessor();
IPaymentGateway paymentGateway = new PaymentAdapter(thirdPartyProcessor);
paymentGateway.ProcessPayment(99.99m);
// 输出: Processing payment of amount: 99.99
}
}
五、适配器模式的优缺点
优点
- 单一职责原则:将接口转换代码从业务逻辑中分离
- 开闭原则:可以引入新的适配器而不影响现有代码
- 提高了类的复用性
缺点
- 增加了系统复杂性(需要引入新的类和接口)
- 在某些情况下,过度使用适配器会使系统变得难以维护
六、适配器模式与其他模式的关系
-
与外观模式:适配器包装一个类,而外观模式包装整个子系统
-
与桥接模式:两者都旨在将抽象与实现解耦,但适配器关注已有接口的兼容性,桥接模式关注提前设计
-
与装饰器模式:适配器提供不同的接口,装饰器提供扩展功能而不改变接口
七、最佳实践
- 当接口不兼容但功能相似时使用适配器模式
- 优先使用对象适配器(组合方式)而非类适配器(继承方式),因为更灵活
- 考虑使用依赖注入来管理适配器的生命周期
- 为适配器编写单元测试以确保转换逻辑正确
适配器模式在C#中特别适用于集成遗留系统、第三方库或处理接口不匹配的情况,是构建可扩展、可维护系统的重要工具。