C#设计模式详解与示例:从入门到精通
设计模式(design patterns)是经过验证的、针对软件开发中常见问题的解决方案。它们并非现成的代码,而是可以针对具体情况进行调整的模板。对于C#开发者而言,掌握设计模式不仅是简历上的加分项,更是构建灵活、可维护、可扩展架构的必要条件。
本文将根据GoF(四人帮)分类法,讲解三大类设计模式:创建型、结构型和行为型。每个模式都将通过C#(.NET)的实际示例进行说明。
创建型模式(Creational Patterns)
这些模式管理对象的创建过程,使系统独立于对象的创建方式。我们来看两个最流行的模式。
单例模式(Singleton)
确保一个类只有一个实例,并提供一个全局访问点。在C#中,为了在多线程环境下安全使用,通常使用Lazy<T>。
public sealed class Logger{ private static readonly Lazy<Logger> _instance = new Lazy<Logger>(() => new Logger());
public static Logger Instance => _instance.Value;
private Logger() { }
public void Log(string message) { Console.WriteLine($"[{DateTime.Now}] {message}"); }}
// 使用方式Logger.Instance.Log("应用程序已启动");工厂方法模式(Factory Method)
定义一个创建对象的接口,但让子类决定实例化哪个类。非常适合在对象类型预先未知的情况下使用。
public interface ITransport{ void Deliver();}
public class Truck : ITransport{ public void Deliver() => Console.WriteLine("陆路运输");}
public class Ship : ITransport{ public void Deliver() => Console.WriteLine("海上运输");}
public abstract class Logistics{ public abstract ITransport CreateTransport();
public void PlanDelivery() { var transport = CreateTransport(); transport.Deliver(); }}
public class RoadLogistics : Logistics{ public override ITransport CreateTransport() => new Truck();}
// 使用方式Logistics logistics = new RoadLogistics();logistics.PlanDelivery(); // 输出:陆路运输结构型模式(Structural Patterns)
这些模式定义了对象之间的组合方式,以确保架构的灵活性和效率。
适配器模式(Adapter)
允许接口不兼容的对象协同工作。常用于集成旧代码或第三方库。
// 客户端期望的目标接口public interface IModernPrinter{ void Print(string text);}
// 具有不兼容接口的旧类public class OldPrinter{ public void PrintOldStyle(string message) { Console.WriteLine($"旧打印机:{message}"); }}
// 适配器public class PrinterAdapter : IModernPrinter{ private readonly OldPrinter _oldPrinter;
public PrinterAdapter(OldPrinter oldPrinter) { _oldPrinter = oldPrinter; }
public void Print(string text) { _oldPrinter.PrintOldStyle(text); }}
// 使用方式IModernPrinter printer = new PrinterAdapter(new OldPrinter());printer.Print("你好,世界!"); // 输出:旧打印机:你好,世界!装饰器模式(Decorator)
动态地为对象添加新的职责,而无需修改其代码。是继承的灵活替代方案。
public interface ICoffee{ double GetCost(); string GetDescription();}
public class SimpleCoffee : ICoffee{