适配器模式👍
1、定义与核心思想
(1)定义
- 适配器模式(Adapter Pattern) 是一种结构型设计模式,用于解决接口不兼容的问题。
- 核心目标是通过一个中间层(适配器),将现有接口转换为客户端期望的接口,使原本无法协同工作的类能够协同工作。
- 例如,电源转换器将不同国家的电压标准统一。
(2)模式类型
- 类适配器:通过继承适配者类并实现目标接口(C#因不支持多重继承,实际应用中较少使用)。
- 对象适配器:通过组合方式持有适配者实例(推荐方式,灵活且符合合成复用原则)。
2、C#代码实现
(1)对象适配器
- 通过组合适配者实例,适配器将
SpecificRequest()转换为Request(),客户端无需直接依赖Adaptee
// 目标接口(客户端期望的接口)
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#不支持多重继承,但可通过实现接口+继承基类模拟
- 局限性:仅适用于适配者为非密封类的情况,且可能导致耦合度较高
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)集成第三方库或遗留代码
- 当引入第三方组件接口与现有系统不兼容时,适配器可隔离变化,避免直接修改外部代码。
- 示例:旧版日志系统适配到新接口:
// 旧日志类(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。
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)跨平台兼容
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)双向适配器
- 允许适配者和目标接口相互调用,适用于需要双向转换的场景:
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)线程安全适配器
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)延迟加载适配器
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)支付网关适配
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)数据格式转换
public class XmlToJsonAdapter : IDataFormatter
{
private XmlParser _xmlParser = new XmlParser();
public string FormatData(string input)
{
var xmlData = _xmlParser.Parse(input);
return JsonConvert.SerializeObject(xmlData);
}
}
桥接模式👍
1、定义与核心思想
(1)定义
- 桥接模式(Bridge Pattern)是一种结构型设计模式,将抽象部分与实现部分分离,使其可以独立变化。
- 核心通过组合关系替代继承,解决多维度的类爆炸问题,提高系统扩展性。
(2)核心思想
- 解耦:抽象层(如形状)与实现层(如渲染方式)通过接口或抽象类组合,而非继承。
- 独立演化:双方变化互不影响,例如新增渲染技术无需修改形状类。
(3)结构及角色
- 抽象类(Abstraction):定义高层接口,持有实现层引用。
- 扩展抽象类(Refined Abstraction):实现抽象类的业务逻辑。
- 实现接口(Implementor):定义底层操作的接口。
- 具体实现类(Concrete Implementor):实现接口的具体功能。
- UML类图示例:
+----------------+ +-------------------+
| IShape |<>---->| IRenderer |
+----------------+ +-------------------+
| +Draw() | | +Render(string) |
+----------------+ +-------------------+
△ △
| |
+----------------+ +-------------------+
| Circle | | VectorRenderer |
+----------------+ +-------------------+
| -radius:double | | +Render() |
+----------------+ +-------------------+
(4)应用场景
- 多维度变化:如GUI控件(控件类型×主题风格)。
- 跨平台开发:业务逻辑与平台实现解耦(如Android/iOS的绘图库)。
- 动态切换实现:运行时切换算法或组件(如日志记录方式)。
2、C#代码实现
- 场景:图形渲染系统,支持不同形状(圆形、方形)和渲染方式(矢量、光栅),避免类爆炸(如
CircleVector、CircleRaster等)。
(1)实现接口(IRenderer)
// 渲染接口
public interface IRenderer
{
void Render(string shapeName);
}
(2)具体实现类(VectorRenderer, RasterRenderer)
// 矢量渲染
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)
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)
// 圆形
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)客户端调用
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的方形
(6)实际应用
- 依赖注入(DI):通过IoC容器自动绑定实现类(如ASP.NET Core中注入
IRenderer)。
- 工厂模式结合:用工厂类动态创建抽象与实现的组合。
- 模板方法扩展:在抽象类中定义默认行为,子类覆盖细节。
3、优缺点分析
(1)优势
- 低耦合:抽象与实现独立扩展。
- 高复用性:同一实现可被多个抽象复用。
- 灵活性:动态组合多维属性。
(2)局限
- 设计复杂度:需提前识别变化的维度。
- 接口冗余:若维度变化少,可能过度设计。
(3)对比其他模式
| 模式 |
核心目标 |
适用场景 |
| 桥接模式 |
解耦多维变化 |
多独立维度的组合(如形状×渲染) |
| 适配器模式 |
解决接口不兼容 |
旧系统适配新接口 |
| 策略模式 |
动态切换算法 |
单一维度的行为替换(如排序算法) |
装饰器模式👍
1、定义与核心思想
(1)定义
- 装饰器模式是一种结构型设计模式,其核心在于动态地为对象添加职责,而无需修改原有类或继承结构。
- 该模式通过将对象包装在装饰器类的实例中,以组合替代继承的方式扩展功能,遵循开闭原则(对扩展开放,对修改关闭)。
(2)应用场景
- 动态功能扩展:如日志记录、权限验证、缓存等
- 避免子类爆炸:当需要多种功能组合时(如不同配置的咖啡加料)
- 运行时行为增强:如UI组件的边框/滚动条动态添加
(3)结构及角色
<<interface>>
IComponent
↑
+------+------+
| |
ConcreteComponent Decorator(抽象)
↑
ConcreteDecoratorA/B
- 关键角色:
- IComponent:定义基础操作的接口(如
Operation())
- ConcreteComponent:实现基础功能的具体类(如基础文本显示)
- Decorator:持有一个IComponent引用,实现相同接口
- ConcreteDecorator:添加具体扩展逻辑(如边框装饰)
- 代码实现要点
- 接口一致性:装饰器必须与组件实现相同接口
- 透明性:客户端无需区分原始对象与装饰后的对象
- 递归组合:装饰器可嵌套多层(如
DecoratorA(DecoratorB(BaseComponent)))
- 生命周期管理:
- 使用
IDisposable确保嵌套对象正确释放
- 避免循环引用(可通过弱引用
WeakReference处理)
2、C#代码实现
(1)案例1:足球比赛阵型调整
- 需求:比赛上下半场动态切换防守/进攻策略而不修改基础类。
// 组件接口
public abstract class OurStrategy {
public abstract void Play(string msg);
}
// 基础策略(防守阵型)
public class DefenseStrategy : OurStrategy {
public override void Play(string msg) {
Console.WriteLine("上半场默认4-4-2防守阵型");
}
}
// 装饰器基类
public abstract class StrategyDecorator : OurStrategy {
protected OurStrategy _strategy;
public StrategyDecorator(OurStrategy strategy) {
_strategy = strategy;
}
public override void Play(string msg) {
_strategy?.Play(msg);
}
}
// 具体装饰器(进攻策略)
public class AttackDecorator : StrategyDecorator {
public AttackDecorator(OurStrategy strategy) : base(strategy) {}
public override void Play(string msg) {
base.Play(msg);
Console.WriteLine("附加进攻策略:三前锋压制");
}
}
// 使用示例
var strategy = new AttackDecorator(new DefenseStrategy());
strategy.Play("下半场调整");
上半场默认4-4-2防守阵型
附加进攻策略:三前锋压制
(2)案例2:电商产品套餐组合
- 需求:灵活组合基础商品与附加服务(如包装、赠品)。
// 抽象组件
public abstract class Product {
public abstract string GetDescription();
public abstract double GetPrice();
}
// 具体组件(基础商品)
public class BasicProduct : Product {
private string _name;
private double _price;
public BasicProduct(string name, double price) {
_name = name;
_price = price;
}
public override string GetDescription() => _name;
public override double GetPrice() => _price;
}
// 装饰器基类
public abstract class ProductDecorator : Product {
protected Product _product;
public ProductDecorator(Product product) {
_product = product;
}
}
// 具体装饰器(礼盒包装)
public class GiftWrapDecorator : ProductDecorator {
public GiftWrapDecorator(Product product) : base(product) {}
public override string GetDescription() =>
$"{_product.GetDescription()} + 豪华礼盒";
public override double GetPrice() =>
_product.GetPrice() + 25.0;
}
// 客户端调用
Product package = new GiftWrapDecorator(
new BasicProduct("景德镇瓷器", 299.0));
Console.WriteLine($"{package.GetDescription()} - 总价:{package.GetPrice()}");
(3)案例3:日志记录装饰器
public class LoggingDecorator : IDataService {
private IDataService _service;
private ILogger _logger;
public LoggingDecorator(IDataService service, ILogger logger) {
_service = service;
_logger = logger;
}
public object GetData(string query) {
_logger.Info($"查询开始: {query}");
var result = _service.GetData(query);
_logger.Info($"查询完成: {result.Length}条记录");
return result;
}
}
(4)案例4:缓存装饰器
public class CacheDecorator : IApiClient {
private IApiClient _client;
private MemoryCache _cache = new MemoryCache();
public CacheDecorator(IApiClient client) {
_client = client;
}
public string Get(string url) {
if(_cache.Contains(url))
return _cache.Get(url) as string;
var data = _client.Get(url);
_cache.Add(url, data, DateTime.Now.AddMinutes(10));
return data;
}
}
(5)案例5:UI组件增强
- 输出:绘制基础文本框 → 添加边框 → 添加滚动条
// 基础文本框
public class TextBox : IControl {
public void Draw() => Console.WriteLine("绘制基础文本框");
}
// 滚动条装饰器
public class ScrollDecorator : ControlDecorator {
public ScrollDecorator(IControl control) : base(control) {}
public override void Draw() {
base.Draw();
Console.WriteLine("添加垂直滚动条");
}
}
// 使用
var textBox = new ScrollDecorator(new BorderDecorator(new TextBox()));
textBox.Draw();
(6)案例6:权限控制管道
public class AuthorizationDecorator : ICommandHandler<TCommand> {
private ICommandHandler<TCommand> _inner;
private IUserContext _userContext;
public AuthorizationDecorator(ICommandHandler<TCommand> inner, IUserContext user) {
_inner = inner;
_userContext = user;
}
public void Handle(TCommand command) {
if(!_userContext.HasPermission(command.RequiredPermission))
throw new SecurityException();
_inner.Handle(command);
}
}
(7)注意事项
- 装饰顺序敏感:某些装饰器的顺序会影响最终结果(如先加密后压缩 vs 先压缩后加密)
- 线程安全:多层装饰器共享状态时需同步控制
- DI容器集成:通过依赖注入框架(如ASP.NET Core)自动装配装饰链
services.AddScoped<IDataService, BasicDataService>();
services.Decorate<IDataService, CacheDecorator>();
services.Decorate<IDataService, LoggingDecorator>();
- AOP替代方案:对于横切关注点(如日志),可结合AOP框架(如PostSharp)实现
(8)最佳实践
- 使用准则:
- 当需要动态、透明地添加职责时优先选择
- 避免超过3层装饰(可通过组合模式优化)
- 对装饰器进行单元测试(包括单独测试和组合测试)
- 性能优化策略:
- 缓存频繁使用的装饰链
- 采用轻量级装饰器(如避免重复初始化)
- 异步执行非关键装饰逻辑(如日志写入)
- 架构影响:
- 促进松耦合架构
- 支持微服务中的装饰链模式(如API网关的过滤链)
- 与领域驱动设计(DDD)中的装饰器应用结合
3、优缺点分析
(1)优势
- 灵活扩展:比继承更灵活,支持运行时动态组合
- 单一职责:每个装饰器只关注单一功能
- 避免类爆炸:通过组合替代多层次继承
(2)局限性
- 对象标识问题:装饰后的对象与原对象类型不同(
is判断可能失效)
- 调试复杂度:多层装饰导致调用链难以追踪
- 性能损耗:每层装饰带来额外调用开销(可通过缓存优化)
(3)对比其他模式
| 模式 |
核心差异 |
适用场景 |
| 策略模式 |
改变对象算法 |
多种算法可替换 |
| 代理模式 |
控制访问/延迟初始化 |
访问控制、虚拟代理 |
| 组合模式 |
处理树形结构 |
UI组件嵌套 |
| 适配器模式 |
接口转换 |
新旧系统兼容 |
外观模式
1、定义与核心思想
(1)定义
- 外观模式(Facade Pattern)是一种结构型设计模式,其核心思想是为复杂的子系统提供一个统一的高层接口,简化客户端调用。
- 通过封装子系统的内部细节,外观模式降低了客户端与子系统之间的耦合度,提升了系统的可维护性和扩展性。
(2)核心目标
- 简化接口:隐藏子系统的复杂性。
- 解耦:减少客户端对子系统的直接依赖。
- 统一入口:提供一致的调用方式。
(3)结构与角色
- Facade(外观类):
- 封装子系统的接口,负责将客户端请求转发到对应的子系统。
- 知道如何组合子系统的方法以满足客户端需求。
- Subsystem Classes(子系统类集合):
(4)适用场景
- 复杂子系统调用:例如微服务架构中的服务聚合。
- 第三方SDK封装:提供简化的API接口。
- 遗留系统改造:通过外观类包装旧代码,逐步重构。
- 分层架构:服务层封装数据访问层和业务逻辑层。
2、C#代码实现
(1)基础实现
- 代码解析
- 子系统类独立实现功能。
- 外观类通过构造函数依赖注入子系统实例。
- 客户端仅需调用外观类的方法即可完成复杂操作
// 子系统接口
public interface ISubsystem
{
void Method1();
void Method2();
}
// 子系统实现类
public class Subsystem1 : ISubsystem
{
public void Method1() => Console.WriteLine("Subsystem1 方法1");
public void Method2() => Console.WriteLine("Subsystem1 方法2");
}
public class Subsystem2 : ISubsystem
{
public void Method1() => Console.WriteLine("Subsystem2 方法1");
public void Method2() => Console.WriteLine("Subsystem2 方法2");
}
// 外观类
public class Facade
{
private readonly ISubsystem _subsystem1;
private readonly ISubsystem _subsystem2;
public Facade(ISubsystem subsystem1, ISubsystem subsystem2)
{
_subsystem1 = subsystem1;
_subsystem2 = subsystem2;
}
// 统一接口方法
public void ExecuteComplexOperation()
{
_subsystem1.Method1();
_subsystem2.Method2();
}
}
// 客户端调用
class Client
{
static void Main()
{
var subsystem1 = new Subsystem1();
var subsystem2 = new Subsystem2();
var facade = new Facade(subsystem1, subsystem2);
facade.ExecuteComplexOperation(); // 输出:Subsystem1 方法1 → Subsystem2 方法2
}
}
(2)微服务下单系统示例
- 适用场景:微服务架构下,订单流程涉及多个子系统的协作
// 物流子系统
public interface ILogisticsSystem
{
bool CheckLogistics(int productId, int cityId);
void NewLogistics(int productId, int cityId);
}
public class LogisticsSystem : ILogisticsSystem
{
public bool CheckLogistics(int productId, int cityId) => true;
public void NewLogistics(int productId, int cityId)
=> Console.WriteLine($"商品[{productId}]从城市[{cityId}]发货");
}
// 库存子系统
public interface IStorageSystem { bool CheckStorage(int productId); }
public class StorageSystem : IStorageSystem
{
public bool CheckStorage(int productId) => true;
}
// 订单子系统
public interface IOrderSystem { void CreateOrder(int productId); }
public class OrderSystem : IOrderSystem
{
public void CreateOrder(int productId)
=> Console.WriteLine($"订单已生成,商品ID:{productId}");
}
// 外观类:下单服务
public class OrderFacade
{
private readonly ILogisticsSystem _logistics;
private readonly IStorageSystem _storage;
private readonly IOrderSystem _order;
public OrderFacade()
{
_logistics = new LogisticsSystem();
_storage = new StorageSystem();
_order = new OrderSystem();
}
public void PlaceOrder(int productId, int cityId)
{
if (_storage.CheckStorage(productId) && _logistics.CheckLogistics(productId, cityId))
{
_order.CreateOrder(productId);
_logistics.NewLogistics(productId, cityId);
}
}
}
// 客户端调用
var facade = new OrderFacade();
facade.PlaceOrder(1001, 101);
// 输出:订单已生成 → 商品发货
(3)智能家居控制示例
public interface IDevice
{
void TurnOn();
void TurnOff();
}
// 子系统:热水器
public class WaterHeater : IDevice
{
public void TurnOn() => Console.WriteLine("热水器已开启");
public void TurnOff() => Console.WriteLine("热水器已关闭");
}
// 子系统:灯光
public class Light : IDevice
{
public void TurnOn() => Console.WriteLine("灯光已开启");
public void TurnOff() => Console.WriteLine("灯光已关闭");
}
// 外观类:智能家居控制器
public class SmartHomeFacade
{
private readonly IDevice _heater;
private readonly IDevice _light;
public SmartHomeFacade(IDevice heater, IDevice light)
{
_heater = heater;
_light = light;
}
public void ActivateHomeMode()
{
_heater.TurnOn();
_light.TurnOn();
}
public void DeactivateHomeMode()
{
_heater.TurnOff();
_light.TurnOff();
}
}
3、进阶用法
(1)依赖注入(DI)优化
- 通过依赖注入(如ASP.NET Core的
IServiceCollection)动态管理子系统实例:
services.AddSingleton<ILogisticsSystem, LogisticsSystem>();
services.AddScoped<OrderFacade>();
(2)异步编程支持
public async Task PlaceOrderAsync(int productId, int cityId)
{
var stockTask = _storage.CheckStorageAsync(productId);
var logisticsTask = _logistics.CheckLogisticsAsync(productId, cityId);
await Task.WhenAll(stockTask, logisticsTask);
// 后续操作...
}
(3)动态外观模式
public class DynamicFacade
{
private Dictionary<string, object> _subsystems = new();
public void AddSubsystem(string key, object subsystem) => _subsystems[key] = subsystem;
public void Execute(string methodName)
{
foreach (var subsystem in _subsystems.Values)
{
var method = subsystem.GetType().GetMethod(methodName);
method?.Invoke(subsystem, null);
}
}
}
4、优缺点分析
(1)优点
- 简化调用:客户端只需与外观类交互,无需了解子系统细节。
- 降低耦合:子系统修改不影响客户端。
- 统一入口:集中管理复杂流程(如事务控制)。
(2)缺点
- 违反开闭原则:新增功能可能需要修改外观类。
- 性能损失:多层封装可能增加调用链。