适配器模式👍
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(); }
}
(2)类适配器
- C#不支持多重继承,但可通过实现接口+继承基类模拟
- 局限性:仅适用于适配者为非密封类的情况,且可能导致耦合度较高
public interface ITarget
{void Request();
}public class Adaptee
{public void SpecificRequest(){Console.WriteLine("Adaptee的方法");}
}
public class Adapter : Adaptee, ITarget
{public void Request(){SpecificRequest();}
}
3、应用场景
(1)集成第三方库或遗留代码
- 当引入第三方组件接口与现有系统不兼容时,适配器可隔离变化,避免直接修改外部代码。
- 示例:旧版日志系统适配到新接口:
public class LegacyLogger
{public void Log(string message, int level){Console.WriteLine($"[Legacy] Level {level}: {message}");}
}
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);
}
public class MySqlAdapter : IDatabase
{private MySqlClient _mysql = new MySqlClient();public void Execute(string query){_mysql.RunQuery(query);}
}
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);
}
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(); var square = new Square(rasterRenderer, 10.0);
square.Draw();
(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(); }
}
(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)缺点
- 违反开闭原则:新增功能可能需要修改外观类。
- 性能损失:多层封装可能增加调用链。