简介这份C#设计模式源码资源面向具备一定C#基础的开发者与软件设计学习者围绕单例、工厂、抽象工厂、建造者、适配器、模板方法、观察者、装饰、代理、组合等经典模式提供可运行的代码实现帮助读者在真实项目中理解模式的应用场景与优缺点提升代码的可读性、可维护性与可扩展性。资源以rar压缩包形式提供整体约3.26MB内容以源码文件为主便于直接编译调试与逐类对照分析。目前已有302人学习下载适合作为设计模式入门到进阶的实践参考。通过阅读源码读者可以掌握线程安全单例、工厂方法的产品创建、建造者模式的导演与建造者协作、观察者模式结合INotifyPropertyChanged的数据绑定以及静态代理与动态代理的实现差异从而在架构设计与重构中更灵活地选用合适模式。1. 从一次代码评审说起为什么C#设计模式源码值得逐行拆某次内部代码评审一位同事提交了一个订单状态流转模块用了一长串if-else判断状态新增一种状态就要改动三处逻辑。评审时有人问了一句“这里为什么不用状态模式”回答是“知道有这个东西但不知道怎么落地”。这个场景很典型——设计模式的概念大家都背过但真正到了C#项目里能把模式用对、用准、用出可维护性的人并不多。这份C#设计模式源码要解决的正是这个断层它不是概念速查表而是一套可以直接跑、可以改、可以对照业务场景复用的代码集合。适合正在做课程设计、毕业设计或者需要在实际项目中引入设计模式却缺少参考实现的开发者。接下来的内容会按“需求拆解→结构设计→模块实现→避坑→验收”的顺序展开把这份源码怎么用、怎么改、怎么讲清楚一次说透。2. 需求拆解与技术选型为什么是C#加设计模式这套组合2.1 从业务痛点反推模式需求设计模式不是凭空选的得先看业务里反复出现什么问题。常见的几类痛点包括对象创建逻辑散落在各处导致改一处崩三处、算法频繁切换却不想动调用方代码、子系统接口太杂需要统一入口、状态或行为随条件动态变化。这些问题在C#项目里尤其突出因为C#是强类型语言接口和抽象类的约束比动态语言更严格一旦结构没设计好后期重构成本很高。这份源码覆盖的模式大致可以按创建型、结构型、行为型三类来组织。创建型解决“对象怎么来”的问题比如单例、工厂方法、抽象工厂、建造者结构型解决“对象怎么组合”的问题比如适配器、装饰器、代理、外观行为型解决“对象怎么协作”的问题比如观察者、策略、状态、命令、责任链。每个模式都对应一个具体的业务场景不是孤立的Demo。通常的做法是先列出项目里所有“变化点”——哪些地方经常改、哪些地方扩展频繁然后对照模式清单找匹配。比如支付方式经常新增就用策略模式订单状态流转复杂就用状态模式日志、缓存这类横切逻辑就用装饰器或代理。2.2 技术栈与运行环境说明这份源码基于C#语言运行在.NET平台上。项目结构通常按模式分类建文件夹每个模式一个独立可运行的控制台或类库项目方便单独调试。核心依赖只有标准库不引入第三方框架这样做的目的是让读者把注意力放在模式本身的结构上而不是被框架的API干扰。代码里会用到接口、抽象类、泛型、委托、事件这些C#特性。比如观察者模式会用event和delegate实现策略模式会用接口加泛型约束工厂模式会用反射或配置文件来解耦。这些特性在C#里是原生支持的不需要额外安装包。提示如果本地没有Visual Studio用dotnetCLI也能编译运行命令是dotnet run前提是已安装对应版本的.NET SDK。2.3 项目目录结构与模块划分源码的目录结构一般长这样DesignPatterns/ ├── Creational/ │ ├── Singleton/ │ ├── FactoryMethod/ │ ├── AbstractFactory/ │ └── Builder/ ├── Structural/ │ ├── Adapter/ │ ├── Decorator/ │ ├── Proxy/ │ └── Facade/ ├── Behavioral/ │ ├── Observer/ │ ├── Strategy/ │ ├── State/ │ ├── Command/ │ └── ChainOfResponsibility/ └── Shared/ └── Interfaces/每个模式文件夹下至少包含三个文件接口定义、具体实现、调用示例。调用示例通常放在Program.cs或单独的Client.cs里用Main方法演示完整流程。Shared文件夹放公共接口比如IOrder、IPayment这类跨模式复用的抽象。这种划分的好处是想学哪个模式就进哪个文件夹不用在几百个文件里翻。想对比两个模式的差异直接并排打开两个文件夹就行。3. 核心模式实现从创建型到行为型的代码落地3.1 创建型模式单例与工厂的C#写法单例模式在C#里有几种写法最推荐的是静态内部类或LazyT方式线程安全且延迟加载。下面是一个用LazyT实现的单例public sealed class ConfigManager { // 使用 LazyT 保证线程安全且延迟初始化 private static readonly LazyConfigManager _instance new LazyConfigManager(() new ConfigManager()); public static ConfigManager Instance _instance.Value; // 私有构造函数防止外部 new private ConfigManager() { // 模拟加载配置 LoadConfig(); } private void LoadConfig() { // 实际项目中这里读文件或数据库 Console.WriteLine(配置已加载); } }这段代码的关键点是sealed防止继承、私有构造函数防止外部实例化、LazyT保证线程安全。参数上没有什么可调的但要注意如果配置加载很耗时LazyT的LazyThreadSafetyMode可以改成PublicationOnly来放宽线程约束不过一般用默认的ExecutionAndPublication就够了。工厂方法模式则用来解耦对象的创建。比如一个支付场景不同支付方式实现同一个接口工厂根据类型返回具体实例public interface IPayment { void Pay(decimal amount); } public class AlipayPayment : IPayment { public void Pay(decimal amount) Console.WriteLine($支付宝支付 {amount} 元); } public class WechatPayment : IPayment { public void Pay(decimal amount) Console.WriteLine($微信支付 {amount} 元); } public static class PaymentFactory { public static IPayment Create(string type) { return type switch { alipay new AlipayPayment(), wechat new WechatPayment(), _ throw new ArgumentException(不支持的支付类型) }; } }调用时只需要PaymentFactory.Create(alipay).Pay(100)新增支付方式时改工厂的switch即可调用方不动。这就是开闭原则的体现——对扩展开放对修改关闭。3.2 结构型模式装饰器与代理的差异与选择装饰器和代理在代码结构上很像都是包装一个对象但意图不同。装饰器是动态给对象加功能代理是控制对对象的访问。下面是一个装饰器的例子给订单服务加日志和缓存public interface IOrderService { void PlaceOrder(string orderId); } public class OrderService : IOrderService { public void PlaceOrder(string orderId) { Console.WriteLine($下单成功{orderId}); } } // 日志装饰器 public class LoggingDecorator : IOrderService { private readonly IOrderService _inner; public LoggingDecorator(IOrderService inner) _inner inner; public void PlaceOrder(string orderId) { Console.WriteLine($[日志] 开始处理订单 {orderId}); _inner.PlaceOrder(orderId); Console.WriteLine($[日志] 订单 {orderId} 处理完毕); } } // 缓存装饰器 public class CachingDecorator : IOrderService { private readonly IOrderService _inner; private readonly HashSetstring _cache new(); public CachingDecorator(IOrderService inner) _inner inner; public void PlaceOrder(string orderId) { if (_cache.Contains(orderId)) { Console.WriteLine($订单 {orderId} 已存在跳过); return; } _inner.PlaceOrder(orderId); _cache.Add(orderId); } }使用时可以层层包装new LoggingDecorator(new CachingDecorator(new OrderService()))。这样日志和缓存逻辑跟业务逻辑完全分离想加就加想撤就撤。代理模式则更适合远程调用、权限控制这类场景。比如一个文件访问接口代理层先检查权限再决定是否调用真实对象。两者的选择标准很简单加功能用装饰器控访问用代理。3.3 行为型模式观察者与策略的事件驱动实现观察者模式在C#里用event实现最自然。比如订单状态变化时通知多个模块public class Order { public event Actionstring OnStatusChanged; private string _status; public string Status { get _status; set { _status value; OnStatusChanged?.Invoke(value); // 触发通知 } } } // 调用方 var order new Order(); order.OnStatusChanged status Console.WriteLine($邮件通知订单状态变为 {status}); order.OnStatusChanged status Console.WriteLine($短信通知订单状态变为 {status}); order.Status 已发货;这里OnStatusChanged是委托事件注册多个订阅者?.Invoke保证没有订阅者时不报错。参数status是状态字符串实际项目里可以换成枚举或自定义类。策略模式则用来封装可互换的算法。比如运费计算不同地区不同规则public interface IShippingStrategy { decimal Calculate(decimal weight); } public class StandardShipping : IShippingStrategy { public decimal Calculate(decimal weight) weight * 5; } public class ExpressShipping : IShippingStrategy { public decimal Calculate(decimal weight) weight * 10 20; } public class ShippingContext { private IShippingStrategy _strategy; public ShippingContext(IShippingStrategy strategy) _strategy strategy; public decimal Execute(decimal weight) _strategy.Calculate(weight); }调用时传入不同策略即可new ShippingContext(new ExpressShipping()).Execute(3)。新增运费规则时只加一个类不改上下文。4. 避坑与常见问题设计模式落地时最容易翻车的五个点4.1 模式过度使用导致类爆炸现象一个简单功能引入了五六个接口和抽象类代码量翻倍维护反而更累。原因把模式当成了目标而不是手段。解决先问“这里真的会变吗”如果变化概率很低直接用简单写法。模式只在变化点明确时才引入。4.2 单例模式在多线程下失效现象单例对象被创建了两次配置加载重复执行。原因用了非线程安全的懒加载写法比如if (_instance null)没有加锁。解决用LazyT或静态构造函数这两种方式由CLR保证线程安全。4.3 装饰器顺序影响结果现象日志装饰器放在缓存装饰器外面导致缓存命中时也打印日志日志量暴增。原因装饰器是层层包装的外层先执行。解决明确每个装饰器的职责缓存应该在最外层拦截日志放在内层只记录真实调用。4.4 观察者模式忘记取消订阅导致内存泄漏现象长时间运行后内存持续增长GC回收不掉。原因事件订阅后没有-取消发布者一直持有订阅者的引用。解决在Dispose或生命周期结束时取消订阅或者用弱事件模式。4.5 策略模式与工厂模式混淆现象把策略的创建逻辑写在了策略类内部导致策略类既管算法又管实例化。原因职责没分清。解决策略只负责算法创建交给工厂或依赖注入容器。两者配合使用但不要混在一起。5. 验收与答辩怎么证明这套源码真的能用5.1 功能验收每个模式独立可运行验收的第一步是确认每个模式都能单独跑起来。通常的做法是每个模式文件夹下都有一个Program.cs用dotnet run执行后能看到预期输出。比如单例模式输出“配置已加载”且只输出一次工厂模式输出不同支付方式的调用结果观察者模式输出多条通知。如果某个模式跑不起来先检查.NET SDK版本是否匹配再看接口和实现类的命名空间是否一致。5.2 扩展验收新增一个模式或修改一个模式光跑通还不够得证明这套结构是可扩展的。我一般会让学生做两件事第一新增一个策略实现类比如“次日达运费”看是否只需要加一个类、改一处工厂配置第二给现有装饰器再加一层“重试装饰器”看是否不影响原有代码。如果能做到只加不改说明开闭原则落地了。5.3 答辩演示用对比法讲清楚模式的价值答辩时不要逐个念代码而是用对比法。先展示一段没有用模式的“坏代码”比如一长串if-else或重复的创建逻辑然后展示用模式重构后的代码重点讲三个点变化点在哪里、模式怎么隔离变化、新增需求时改哪里。评委通常关心的是“你为什么选这个模式”和“不用行不行”提前准备好这两个问题的答案。下面是一个简单的验收检查表可以照着过一遍检查项通过标准编译运行每个模式独立dotnet run无报错输出正确控制台输出与预期一致扩展测试新增一个实现类调用方代码不变线程安全单例模式多线程测试无重复实例内存检查观察者模式取消订阅后无泄漏5.4 一个我踩过的坑早期做代码评审时我看到一个项目里用了七八种设计模式觉得结构很漂亮。结果需求一变发现模式之间耦合太紧改一个工厂方法导致三个装饰器报错。从那以后我每次引入模式前都强制走一遍“变化点清单”先列出所有可能变的地方再决定用哪个模式绝不为模式而模式。希望这套源码和上面的验收方法能帮你少走同样的弯路。本文还有配套的精品资源点击获取