// 目标接口(客户端期望的接口)
public interface ITarget
{
void Request();
}
// 适配者类(需被适配的类)
public class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Adaptee的特定请求方法");
}
}
// 适配器类
public class Adapter : ITarget
{
private readonly Adaptee _adaptee;
public Adapter(Adaptee adaptee)
{
_adaptee = adaptee;
}
public void Request()
{
// 调用适配者的方法
_adaptee.SpecificRequest();
}
}
// 客户端调用
class Program
{
static void Main(string[] args)
{
Adaptee adaptee = new Adaptee();
ITarget target = new Adapter(adaptee);
target.Request(); // 输出:Adaptee的特定请求方法
}
}
(2)类适配器
C#不支持多重继承,但可通过实现接口+继承基类模拟
局限性:仅适用于适配者为非密封类的情况,且可能导致耦合度较高
csharp复制代码
public interface ITarget
{
void Request();
}
public class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("Adaptee的方法");
}
}
// 类适配器(继承Adaptee并实现ITarget)
public class Adapter : Adaptee, ITarget
{
public void Request()
{
SpecificRequest();
}
}
3、应用场景
(1)集成第三方库或遗留代码
当引入第三方组件接口与现有系统不兼容时,适配器可隔离变化,避免直接修改外部代码。
示例:旧版日志系统适配到新接口:
csharp复制代码
// 旧日志类(Adaptee)
public class LegacyLogger
{
public void Log(string message, int level)
{
Console.WriteLine($"[Legacy] Level {level}: {message}");
}
}
// 新日志接口(Target)
public interface ILogger
{
void Info(string message);
void Error(string message);
}
// 适配器
public class LoggerAdapter : ILogger
{
private LegacyLogger _legacyLogger = new LegacyLogger();
public void Info(string message)
{
_legacyLogger.Log(message, 1);
}
public void Error(string message)
{
_legacyLogger.Log(message, 3);
}
}
(2)统一多数据源接口
例如将不同数据库(SQL Server、MySQL)的访问接口统一为IDatabase。
csharp复制代码
public interface IDatabase
{
void Execute(string query);
}
// MySQL适配器
public class MySqlAdapter : IDatabase
{
private MySqlClient _mysql = new MySqlClient();
public void Execute(string query)
{
_mysql.RunQuery(query);
}
}
// SQL Server适配器
public class SqlServerAdapter : IDatabase
{
private SqlClient _sql = new SqlClient();
public void Execute(string query)
{
_sql.ExecuteCommand(query);
}
}
(3)跨平台兼容
在跨平台应用中,适配不同操作系统的文件系统接口。
csharp复制代码
public interface IFileSystem
{
void SaveFile(string path, byte[] data);
}
// Linux系统适配器
public class LinuxFileAdapter : IFileSystem
{
public void SaveFile(string path, byte[] data)
{
File.WriteAllBytes($"/mnt/{path}", data);
}
}
4、扩展与优化
(1)双向适配器
允许适配者和目标接口相互调用,适用于需要双向转换的场景:
csharp复制代码
public class BiDirectionalAdapter : ITarget, IAdaptee
{
private ITarget _target;
private IAdaptee _adaptee;
public BiDirectionalAdapter(ITarget target, IAdaptee adaptee)
{
_target = target;
_adaptee = adaptee;
}
public void Request()
{
_adaptee.SpecificRequest();
}
public void SpecificRequest()
{
_target.Request();
}
}
(2)线程安全适配器
通过锁机制确保多线程环境下的安全调用:
csharp复制代码
public class ThreadSafeAdapter : ITarget
{
private readonly Adaptee _adaptee;
private readonly object _lock = new object();
public ThreadSafeAdapter(Adaptee adaptee)
{
_adaptee = adaptee;
}
public void Request()
{
lock (_lock)
{
_adaptee.SpecificRequest();
}
}
}
(3)延迟加载适配器
推迟适配者实例化,优化资源使用:
csharp复制代码
public class LazyAdapter : ITarget
{
private Lazy<Adaptee> _lazyAdaptee;
public LazyAdapter()
{
_lazyAdaptee = new Lazy<Adaptee>(() => new Adaptee());
}
public void Request()
{
_lazyAdaptee.Value.SpecificRequest();
}
}
(4)与其他模式的结合
与工厂模式结合:通过工厂创建适配器,隐藏实例化细节。
与装饰器模式结合:在适配过程中添加额外功能(如日志记录)。
与策略模式结合:动态选择不同的适配策略。
5、优缺点分析
(1)优点
解耦性:隔离客户端与适配者的直接依赖。
复用性:重用现有类,无需修改其代码。
扩展性:支持多适配者组合,灵活应对变化。
(2)缺点
复杂性:过度使用会导致系统结构复杂化。
性能损耗:多层间接调用可能影响性能(可通过缓存优化)。
6、实际案例
(1)支付网关适配
统一支付宝、微信支付等不同接口:
csharp复制代码
public interface IPaymentGateway
{
void Pay(decimal amount);
}
public class WeChatPaymentAdapter : IPaymentGateway
{
private WeChatPay _wechatPay = new WeChatPay();
public void Pay(decimal amount)
{
_wechatPay.Transfer(amount);
}
}
(2)数据格式转换
将XML数据转换为JSON格式输出:
csharp复制代码
public class XmlToJsonAdapter : IDataFormatter
{
private XmlParser _xmlParser = new XmlParser();
public string FormatData(string input)
{
var xmlData = _xmlParser.Parse(input);
return JsonConvert.SerializeObject(xmlData);
}
}
// 渲染接口
public interface IRenderer
{
void Render(string shapeName);
}
(2)具体实现类(VectorRenderer, RasterRenderer)
csharp复制代码
// 矢量渲染
public class VectorRenderer : IRenderer
{
public void Render(string shapeName)
{
Console.WriteLine($"矢量渲染:{shapeName}");
}
}
// 光栅渲染
public class RasterRenderer : IRenderer
{
public void Render(string shapeName)
{
Console.WriteLine($"光栅渲染:{shapeName}");
}
}
(3)抽象类(Shape)
csharp复制代码
public abstract class Shape
{
protected IRenderer Renderer;
public string Name { get; set; }
protected Shape(IRenderer renderer)
{
Renderer = renderer;
}
public abstract void Draw();
}
(4)扩展抽象类(Circle, Square)
csharp复制代码
// 圆形
public class Circle : Shape
{
public double Radius { get; set; }
public Circle(IRenderer renderer, double radius) : base(renderer)
{
Radius = radius;
Name = "圆形";
}
public override void Draw()
{
Renderer.Render($"半径={Radius}的{Name}");
}
}
// 方形
public class Square : Shape
{
public double SideLength { get; set; }
public Square(IRenderer renderer, double side) : base(renderer)
{
SideLength = side;
Name = "方形";
}
public override void Draw()
{
Renderer.Render($"边长={SideLength}的{Name}");
}
}
(5)客户端调用
csharp复制代码
var vectorRenderer = new VectorRenderer();
var rasterRenderer = new RasterRenderer();
var circle = new Circle(vectorRenderer, 5.0);
circle.Draw(); // 输出:矢量渲染:半径=5的圆形
var square = new Square(rasterRenderer, 10.0);
square.Draw(); // 输出:光栅渲染:边长=10的方形