C#怎么实现装饰器模式_C# Decorator设计模式方法教程【技巧】
作者:WarmHope
时间:2026-07-17
浏览:2
装配器模式在 C# 里到底怎么落地?很多人第一反应是找类似 Python 的 `@decorator` 语法糖,或者搜 `[Decorator]` 特性,结果折腾半天发现根本没有内置支持。其实核心思路特别简单:**不碰原类,靠接口 + 组合 + 委托动态加行为**。下面一步步拆开看,顺便把容易踩的坑
本文目录
先别急着写代码,得先统一“可装饰”的入口。装饰器的本质是“同类型套一层”,所以必须有一个公共接口来定义契约。比如日志场景,先定义 `ILogger` 接口,所有具体实现(原始类、装饰器类)都实现它:
```csharp
public interface ILogger
{
void Log(string message);
}
```
这里有个容易犯的错误:有人试图用抽象类代替接口,结果装饰器既不能继承原始实现,又没法独立扩展,最后搞出奇怪的继承树。还有的直接从 `FileLogger` 派生 `TimestampLogger`,这种写法只能装饰固定一类,完全失去复用价值。记住:接口是必须的,抽象类不行。
写装饰器类:组合 + 转发 + 增强
装饰器本身是个具体类,构造时接收一个 `ILogger` 实例——这实例可以是原始实现,也可以是另一个装饰器。然后在自己的 `Log` 方法里先做增强逻辑,再调用被装饰对象的 `Log` 转发下去: ```csharp public class TimestampLogger : ILogger { private readonly ILogger _inner; public TimestampLogger(ILogger inner) => _inner = inner; public void Log(string message) { var stamped = $"[{DateTime.Now:HH:mm:ss}] {message}"; _inner.Log(stamped); // 转发给下一层 } } ``` 几个关键点:构造函数参数必须用接口类型(`ILogger`),不能用 `ConsoleLogger` 这种具体类;装饰器内部不 `new` 任何具体实现,靠外部注入,否则就没法链式嵌套。增强逻辑可以放在转发前(前置处理),也可以放在转发后(后置处理),甚至可以直接拦截不转发——比如权限装饰器判断不通过就直接 `return`。运行时组装装饰器链,别硬编码
装饰器的价值在于灵活组合,别写死成 `new TimestampLogger(new FileLogger())` 这种固定链。推荐用工厂方法或者依赖注入容器来管理。手动组装示例(适合测试或简单场景): ```csharp ILogger logger = new TimestampLogger( new RetryLogger( new ConsoleLogger())); ``` 如果用了 `Microsoft.Extensions.DependencyInjection`,注意注册顺序:最后注册的装饰器最先执行(因为它是最外层)。比如: ```csharp services.AddSingleton容易被忽略的性能与生命周期问题
每层装饰器都是一次对象分配和虚方法调用。如果日志频率很高(比如每毫秒一次),堆栈深度超过5层就可能引发 GC 压力,间接影响吞吐。更隐蔽的问题:装饰器若持有 `IDisposable` 资源(比如打开文件流),必须确保整个链能正确释放——接口本身没继承 `IDisposable`,得自己约定,或者额外封装一个 `IDisposableLogger`。 另外,装饰器里的状态(比如计数器、缓存)是否该跨请求共享?多数场景应该无状态,否则多线程下容易出错;真要状态的话,得用 `AsyncLocal
作者最新文章
漫蛙漫画官网首页登录入口
2026-10-28 19:02
mindmanager怎么使用 思维导图入门
2026-10-27 09:54
Word2016怎么移除文档空白页
2026-10-16 22:30
endnote怎么引用中文参考文献格式设置教程
2026-10-14 17:25
sql条件判断字符串不包含某个字符串的方法详解
2026-10-13 17:39
热门文章
更多
精品专题
更多
Mac软件
更多
WINDOWS
更多

































