23种设计模式概述详述(C#代码示例)
文章目录
- 1. 引言
- 1.1 设计模式的价值
- 1.2 设计模式的分类
- 2. 面向对象设计原则
- 2.1 单一职责原则 (SRP)
- 2.2 开放封闭原则 (OCP)
- 2.3 里氏替换原则 (LSP)
- 2.4 接口隔离原则 (ISP)
- 2.5 依赖倒置原则 (DIP)
- 2.6 合成复用原则 (CRP)
- 2.7 迪米特法则 (LoD)
- 3. 创建型设计模式
- 3.1 单例模式 (Singleton)
- 3.2 工厂方法模式 (Factory Method)
- 3.3 抽象工厂模式 (Abstract Factory)
- 3.4 建造者模式 (Builder)
- 3.5 原型模式 (Prototype)
- 4. 结构型设计模式
- 4.1 适配器模式 (Adapter)
- 4.2 桥接模式 (Bridge)
- 4.3 组合模式 (Composite)
- 4.4 装饰器模式 (Decorator)
- 4.5 外观模式 (Facade)
- 4.6 享元模式 (Flyweight)
- 4.7 代理模式 (Proxy)
- 5. 行为型设计模式
- 5.1 观察者模式 (Observer)
- 5.2 策略模式 (Strategy)
- 5.3 模板方法模式 (Template Method)
- 5.4 命令模式 (Command)
- 5.5 迭代器模式 (Iterator)
- 5.6 状态模式 (State)
- 6. 总结与展望
- 6.1 设计模式的优缺点
- 6.2 选择合适的设计模式
- 6.3 设计模式的演进
- 6.4 学习资源
- 7. 结语

1. 引言
设计模式是软件开发中经过验证的、用于解决特定设计问题的通用解决方案。它们代表了众多软件开发者在面对同类问题时积累的最佳实践和经验。设计模式不是现成的代码,而是一种思想、一种方法论,它为软件设计中的常见问题提供了可重用的解决方案。
1994年,Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides(被称为"四人帮"或"Gang of Four",简称GoF)出版了《设计模式:可复用面向对象软件的基础》一书,系统地介绍了23种经典设计模式,这些模式至今仍被广泛应用于软件开发中。
1.1 设计模式的价值
- 提高开发效率:设计模式提供了经过验证的解决方案,避免了"重新发明轮子"
- 提高代码质量:设计模式有助于创建更加灵活、可维护和可扩展的系统
- 促进团队沟通:设计模式提供了一种共同的语言,使团队成员能够更有效地交流设计理念
- 降低维护成本:设计良好的系统更容易理解和修改,减少了维护成本
- 应对变化:设计模式考虑了系统的可扩展性,使系统更好地应对需求变化
1.2 设计模式的分类
GoF设计模式按其目的可分为三大类:
- 创建型模式:处理对象的创建方式,确保对象创建适合于特定场景
- 结构型模式:处理类和对象的组合,组成更大的结构
- 行为型模式:关注对象之间的通信和责任分配
2. 面向对象设计原则
设计模式遵循一系列面向对象设计原则,这些原则指导着模式的创建和应用。理解这些原则对于正确应用设计模式至关重要。
2.1 单一职责原则 (SRP)
一个类应该只有一个引起它变化的原因。换句话说,一个类应该只负责一项职责。
// 违反单一职责原则的示例
public class UserManager
{// 用户管理相关职责public void AddUser(string username) { /* ... */ }public void RemoveUser(string username) { /* ... */ }// 报表生成相关职责 - 不应该在这个类中public void GenerateUserReport() { /* ... */ }public void ExportUserDataToCSV() { /* ... */ }
}// 符合单一职责原则的示例
public class UserManager
{// 仅包含用户管理相关职责public void AddUser(string username) { /* ... */ }public void RemoveUser(string username) { /* ... */ }
}public class UserReportGenerator
{// 专门负责报表生成public void GenerateUserReport() { /* ... */ }public void ExportUserDataToCSV() { /* ... */ }
}
2.2 开放封闭原则 (OCP)
软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着当需要增加新功能时,应该通过扩展现有代码而不是修改它来实现。
// 违反开放封闭原则的示例
public class Rectangle
{public double Width { get; set; }public double Height { get; set; }
}public class AreaCalculator
{public double CalculateArea(object shape){// 每次添加新形状都需要修改这个方法if (shape is Rectangle rectangle){return rectangle.Width * rectangle.Height;}// 如果添加圆形,就需要修改此方法return 0;}
}// 符合开放封闭原则的示例
public interface IShape
{double CalculateArea();
}public class Rectangle : IShape
{public double Width { get; set; }public double Height { get; set; }public double CalculateArea(){return Width * Height;}
}public class Circle : IShape
{public double Radius { get; set; }public double CalculateArea(){return Math.PI * Radius * Radius;}
}// 现在添加新形状不需要修改此类
public class AreaCalculator
{public double CalculateArea(IShape shape){return shape.CalculateArea();}
}
2.3 里氏替换原则 (LSP)
子类型必须能够替换其基类型。这意味着程序中的对象应该可以被其子类的实例所替换,而不影响程序的正确性。
// 违反里氏替换原则的示例
public class Bird
{public virtual void Fly(){// 飞行的实现}
}public class Ostrich : Bird
{public override void Fly(){// 鸵鸟不能飞,这里会抛出异常或者空实现throw new NotSupportedException("鸵鸟不能飞行");}
}// 符合里氏替换原则的示例
public abstract class Bird
{// 通用鸟类行为public abstract void Move();
}public class FlyingBird : Bird
{public override void Move(){// 飞行实现}public virtual void Fly(){// 飞行的具体实现}
}public class NonFlyingBird : Bird
{public override void Move(){// 非飞行鸟类的移动实现(例如行走)}
}
2.4 接口隔离原则 (ISP)
客户端不应该被迫依赖于它们不使用的方法。这个原则建议将大接口分解为更小、更具体的接口。
// 违反接口隔离原则的示例
public interface IWorker
{void Work();void Eat();void Sleep();
}public class Human : IWorker
{public void Work() { /* ... */ }public void Eat() { /* ... */ }public void Sleep() { /* ... */ }
}public class Robot : IWorker
{public void Work() { /* ... */ }public void Eat() { /* 机器人不需要进食,但被迫实现 */ }public void Sleep() { /* 机器人不需要睡觉,但被迫实现 */ }
}// 符合接口隔离原则的示例
public interface IWorkable
{void Work();
}public interface IEatable
{void Eat();
}public interface ISleepable
{void Sleep();
}public class Human : IWorkable, IEatable, ISleepable
{public void Work() { /* ... */ }public void Eat() { /* ... */ }public void Sleep() { /* ... */ }
}public class Robot : IWorkable
{public void Work() { /* ... */ }// 不需要实现不相关的接口
}
2.5 依赖倒置原则 (DIP)
高层模块不应该依赖于低层模块,二者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。
// 违反依赖倒置原则的示例
public class LightBulb
{public void TurnOn() { /* ... */ }public void TurnOff() { /* ... */ }
}public class Switch
{private readonly LightBulb _bulb;// 直接依赖具体实现public Switch(){_bulb = new LightBulb();}public void Toggle(bool isOn){if (isOn)_bulb.TurnOn();else_bulb.TurnOff();}
}// 符合依赖倒置原则的示例
public interface ISwitchable
{void TurnOn();void TurnOff();
}public class LightBulb : ISwitchable
{public void TurnOn() { /* ... */ }public void TurnOff() { /* ... */ }
}public class Fan : ISwitchable
{public void TurnOn() { /* ... */ }public void TurnOff() { /* ... */ }
}public class Switch
{private readonly ISwitchable _device;// 依赖抽象,而非具体实现public Switch(ISwitchable device){_device = device;}public void Toggle(bool isOn){if (isOn)_device.TurnOn();else_device.TurnOff();}
}
2.6 合成复用原则 (CRP)
尽量使用对象组合,而不是通过继承来达到复用的目的。
// 违反合成复用原则的示例 - 通过继承实现复用
public class Database
{public void Connect() { /* ... */ }public void Disconnect() { /* ... */ }public void ExecuteQuery(string query) { /* ... */ }
}public class SpecializedDatabase : Database
{// 通过继承复用Database的功能public void ExecuteSpecialQuery() { Connect();ExecuteQuery("special query");Disconnect();}
}// 符合合成复用原则的示例 - 通过组合实现复用
public class DatabaseService
{private readonly Database _database;public DatabaseService(Database database){_database = database;}// 通过组合复用Database的功能public void ExecuteSpecialQuery(){_database.Connect();_database.ExecuteQuery("special query");_database.Disconnect();}
}
2.7 迪米特法则 (LoD)
一个对象应该对其他对象保持最少的了解,只与它的"朋友"交谈。这个原则也被称为"最少知识原则"。
// 违反迪米特法则的示例
public class Customer
{public Wallet Wallet { get; set; }
}public class Wallet
{public decimal Money { get; set; }
}public class ShopKeeper
{public void ProcessPayment(Customer customer, decimal amount){// 直接访问客户的钱包,违反了迪米特法则if (customer.Wallet.Money >= amount){customer.Wallet.Money -= amount;}}
}// 符合迪米特法则的示例
public class Customer
{private Wallet _wallet;public Customer(){_wallet = new Wallet();}// 提供方法处理付款,封装钱包的访问public bool MakePayment(decimal amount){if (_wallet.Money >= amount){_wallet.Money -= amount;return true;}return false;}
}public class ShopKeeper
{public void ProcessPayment(Customer customer, decimal amount){// 不直接访问客户的钱包,而是请求客户处理付款bool paymentSuccessful = customer.MakePayment(amount);if (paymentSuccessful){// 处理成功的付款}}
}
3. 创建型设计模式
创建型设计模式关注对象的创建过程,帮助我们以更灵活的方式创建对象,而不是直接使用new操作符。
3.1 单例模式 (Singleton)
单例模式确保一个类只有一个实例,并提供一个全局访问点。
C#实现示例:
/// <summary>
/// 单例模式的线程安全实现
/// </summary>
public sealed class Singleton
{// 私有静态实例,使用volatile确保多线程访问的可见性private static volatile Singleton _instance;// 用于锁定的对象private static readonly object _lock = new object();// 私有构造函数,防止外部实例化private Singleton(){// 初始化代码}/// <summary>/// 获取单例实例的全局访问点/// </summary>public static Singleton Instance{get{// 双重检查锁定模式if (_instance == null){lock (_lock){if (_instance == null){_instance = new Singleton();}}}return _instance;}}/// <summary>/// 业务方法示例/// </summary>public void DoSomething(){Console.WriteLine("单例正在执行操作...");}
}// 使用示例
public class Program
{public static void Main(){// 不能通过构造函数创建实例// Singleton singleton = new Singleton(); // 编译错误// 通过全局访问点获取实例Singleton instance1 = Singleton.Instance;Singleton instance2 = Singleton.Instance;// 验证两个实例是同一个对象Console.WriteLine($"实例是相同的: {ReferenceEquals(instance1, instance2)}");// 调用实例方法instance1.DoSomething();}
}
3.2 工厂方法模式 (Factory Method)
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类。工厂方法让一个类的实例化延迟到其子类。
C#实现示例:
/// <summary>
/// 产品接口,定义工厂方法创建的对象的接口
/// </summary>
public interface IProduct
{string Operation();
}/// <summary>
/// 具体产品A,实现产品接口
/// </summary>
public class ConcreteProductA : IProduct
{public string Operation(){return "结果来自具体产品A";}
}/// <summary>
/// 具体产品B,实现产品接口
/// </summary>
public class ConcreteProductB : IProduct
{public string Operation(){return "结果来自具体产品B";}
}/// <summary>
/// 创建者抽象类,声明工厂方法
/// </summary>
public abstract class Creator
{/// <summary>/// 工厂方法 - 由子类实现以创建具体产品/// </summary>public abstract IProduct FactoryMethod();/// <summary>/// 使用工厂方法的核心业务逻辑/// </summary>public string SomeOperation(){// 调用工厂方法创建产品var product = FactoryMethod();// 使用产品return $"创建者: 与 {product.Operation()} 一起工作";}
}/// <summary>
/// 具体创建者A,创建具体产品A
/// </summary>
public class ConcreteCreatorA : Creator
{public override IProduct FactoryMethod(){return new ConcreteProductA();}
}/// <summary>
/// 具体创建者B,创建具体产品B
/// </summary>
public class ConcreteCreatorB : Creator
{public override IProduct FactoryMethod(){return new ConcreteProductB();}
}// 使用示例
public class Program
{public static void Main(){Console.WriteLine("使用具体创建者A:");ClientCode(new ConcreteCreatorA());Console.WriteLine("\n使用具体创建者B:");ClientCode(new ConcreteCreatorB());}/// <summary>/// 客户端代码使用创建者,但不关心具体是哪个创建者/// </summary>public static void ClientCode(Creator creator){Console.WriteLine($"客户端代码: {creator.SomeOperation()}");}
}
3.3 抽象工厂模式 (Abstract Factory)
抽象工厂模式提供一个创建相关或依赖对象家族的接口,而不明确指定它们的具体类。
C#实现示例:
/// <summary>
/// 抽象产品A接口
/// </summary>
public interface IAbstractProductA
{string UsefulFunctionA();
}/// <summary>
/// 具体产品A1 - 风格1的产品A
/// </summary>
public class ConcreteProductA1 : IAbstractProductA
{public string UsefulFunctionA(){return "产品A1的结果";}
}/// <summary>
/// 具体产品A2 - 风格2的产品A
/// </summary>
public class ConcreteProductA2 : IAbstractProductA
{public string UsefulFunctionA(){return "产品A2的结果";}
}/// <summary>
/// 抽象产品B接口
/// </summary>
public interface IAbstractProductB
{string UsefulFunctionB();// 产品B可以与产品A协作string AnotherUsefulFunctionB(IAbstractProductA collaborator);
}/// <summary>
/// 具体产品B1 - 风格1的产品B
/// </summary>
public class ConcreteProductB1 : IAbstractProductB
{public string UsefulFunctionB(){return "产品B1的结果";}public string AnotherUsefulFunctionB(IAbstractProductA collaborator){var result = collaborator.UsefulFunctionA();return $"B1与({result})协作的结果";}
}/// <summary>
/// 具体产品B2 - 风格2的产品B
/// </summary>
public class ConcreteProductB2 : IAbstractProductB
{public string UsefulFunctionB(){return "产品B2的结果";}public string AnotherUsefulFunctionB(IAbstractProductA collaborator){var result = collaborator.UsefulFunctionA();return $"B2与({result})协作的结果";}
}/// <summary>
/// 抽象工厂接口 - 声明一组用于创建产品家族的方法
/// </summary>
public interface IAbstractFactory
{IAbstractProductA CreateProductA();IAbstractProductB CreateProductB();
}/// <summary>
/// 具体工厂1 - 创建风格1的产品家族
/// </summary>
public class ConcreteFactory1 : IAbstractFactory
{public IAbstractProductA CreateProductA(){return new ConcreteProductA1();}public IAbstractProductB CreateProductB(){return new ConcreteProductB1();}
}/// <summary>
/// 具体工厂2 - 创建风格2的产品家族
/// </summary>
public class ConcreteFactory2 : IAbstractFactory
{public IAbstractProductA CreateProductA(){return new ConcreteProductA2();}public IAbstractProductB CreateProductB(){return new ConcreteProductB2();}
}// 使用示例
public class Program
{public static void Main(){// 使用第一个工厂创建产品Console.WriteLine("客户端: 使用第一个工厂类型...");ClientCode(new ConcreteFactory1());// 使用第二个工厂创建产品Console.WriteLine("\n客户端: 使用第二个工厂类型...");ClientCode(new ConcreteFactory2());}/// <summary>/// 客户端代码仅通过抽象类型工作,不关心具体工厂和产品/// </summary>public static void ClientCode(IAbstractFactory factory){var productA = factory.CreateProductA();var productB = factory.CreateProductB();Console.WriteLine(productA.UsefulFunctionA());Console.WriteLine(productB.UsefulFunctionB());Console.WriteLine(productB.AnotherUsefulFunctionB(productA));}
}
3.4 建造者模式 (Builder)
建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
C#实现示例:
/// <summary>
/// 产品类 - 表示被构建的复杂对象
/// </summary>
public class Product
{// 产品可以由多个部分组成private List<string> _parts = new List<string>();/// <summary>/// 添加产品部件/// </summary>public void Add(string part){_parts.Add(part);}/// <summary>/// 列出所有产品部件/// </summary>public string ListParts(){return $"产品部件: {string.Join(", ", _parts)}\n";}
}/// <summary>
/// 生成器接口 - 声明构建产品各个部分的方法
/// </summary>
public interface IBuilder
{void BuildPartA();void BuildPartB();void BuildPartC();Product GetProduct();
}/// <summary>
/// 具体生成器 - 实现构建和装配各个部件的接口
/// </summary>
public class ConcreteBuilder : IBuilder
{private Product _product = new Product();/// <summary>/// 重置生成器实例,以便重新构建另一个产品/// </summary>public ConcreteBuilder(){Reset();}private void Reset(){_product = new Product();}/// <summary>/// 构建产品的A部分/// </summary>public void BuildPartA(){_product.Add("部件A1");}/// <summary>/// 构建产品的B部分/// </summary>public void BuildPartB(){_product.Add("部件B1");}/// <summary>/// 构建产品的C部分/// </summary>public void BuildPartC(){_product.Add("部件C1");}/// <summary>/// 获取构建好的产品/// 注意:此方法在实际应用中通常会重置生成器/// </summary>public Product GetProduct(){Product result = _product;Reset();return result;}
}/// <summary>
/// 指导者类 - 定义构建产品的顺序
/// </summary>
public class Director
{private IBuilder _builder;/// <summary>/// 设置使用的生成器/// </summary>public void SetBuilder(IBuilder builder){_builder = builder;}/// <summary>/// 构建最小可行产品/// </summary>public void BuildMinimalViableProduct(){_builder.BuildPartA();}/// <summary>/// 构建完整功能产品/// </summary>public void BuildFullFeaturedProduct(){_builder.BuildPartA();_builder.BuildPartB();_builder.BuildPartC();}
}// 使用示例
public class Program
{public static void Main(){// 创建生成器var builder = new ConcreteBuilder();// 创建指导者var director = new Director();// 设置指导者使用的生成器director.SetBuilder(builder);// 使用指导者创建不同配置的产品Console.WriteLine("基本产品:");director.BuildMinimalViableProduct();Console.WriteLine(builder.GetProduct().ListParts());Console.WriteLine("完整产品:");director.BuildFullFeaturedProduct();Console.WriteLine(builder.GetProduct().ListParts());// 不使用指导者,直接使用生成器Console.WriteLine("自定义产品:");builder.BuildPartA();builder.BuildPartC();Console.WriteLine(builder.GetProduct().ListParts());}
}
3.5 原型模式 (Prototype)
原型模式通过复制现有的对象来创建新对象,而不是通过实例化。
C#实现示例:
/// <summary>
/// 原型接口 - 声明克隆方法
/// </summary>
public interface IPrototype
{IPrototype Clone();
}/// <summary>
/// 具体原型A - 实现克隆方法
/// </summary>
public class ConcretePrototypeA : IPrototype
{/// <summary>/// 原型的属性/// </summary>public string Property { get; set; }public ConcretePrototypeA(string property){Property = property;}/// <summary>/// 创建当前对象的浅表副本/// </summary>public IPrototype Clone(){// 在这个简单示例中,执行浅复制就足够了return new ConcretePrototypeA(Property);}
}/// <summary>
/// 包含引用类型属性的原型 - 实现深复制
/// </summary>
public class Person : IPrototype
{/// <summary>/// 值类型属性/// </summary>public int Age { get; set; }/// <summary>/// 引用类型属性/// </summary>public string Name { get; set; }/// <summary>/// 包含另一个引用类型的属性/// </summary>public Address Address { get; set; }public Person(int age, string name, Address address){Age = age;Name = name;Address = address;}/// <summary>/// 创建当前对象的深表副本/// </summary>public IPrototype Clone(){// 创建一个新的Address对象,而不是共享同一个引用Address clonedAddress = null;if (Address != null){clonedAddress = new Address(Address.Street, Address.City, Address.Country);}// 返回包含新Address对象的新Person实例return new Person(Age, Name, clonedAddress);}public override string ToString(){return $"Person[Age={Age}, Name={Name}, Address={Address}]";}
}/// <summary>
/// 用于演示深复制的地址类
/// </summary>
public class Address
{public string Street { get; set; }public string City { get; set; }public string Country { get; set; }public Address(string street, string city, string country){Street = street;City = city;Country = country;}public override string ToString(){return $"Address[Street={Street}, City={City}, Country={Country}]";}
}// 使用示例
public class Program
{public static void Main(){// 使用简单原型ConcretePrototypeA prototypeA = new ConcretePrototypeA("测试");ConcretePrototypeA cloneA = (ConcretePrototypeA)prototypeA.Clone();Console.WriteLine($"原始对象属性值: {prototypeA.Property}");Console.WriteLine($"克隆对象属性值: {cloneA.Property}");Console.WriteLine($"是否为同一实例: {ReferenceEquals(prototypeA, cloneA)}");// 展示深复制Address address = new Address("中关村大街1号", "北京", "中国");Person original = new Person(30, "张三", address);Person clone = (Person)original.Clone();Console.WriteLine("\n原始对象:");Console.WriteLine(original);Console.WriteLine("克隆对象:");Console.WriteLine(clone);// 修改原始对象的地址,验证深复制是否成功original.Address.Street = "天安门广场";Console.WriteLine("\n修改原始对象地址后:");Console.WriteLine("原始对象:");Console.WriteLine(original);Console.WriteLine("克隆对象:");Console.WriteLine(clone);Console.WriteLine($"地址是否为同一实例: {ReferenceEquals(original.Address, clone.Address)}");}
}
4. 结构型设计模式
结构型设计模式关注类和对象的组合。它们在不同的对象之间建立关系,使得这些对象能够协同工作,形成更大的结构。
4.1 适配器模式 (Adapter)
适配器模式允许将一个类的接口转换成客户端期望的另一个接口,使得原本不兼容的类可以在一起工作。
C#实现示例:
/// <summary>
/// 目标接口 - 客户端期望的接口
/// </summary>
public interface ITarget
{string Request();
}/// <summary>
/// 适配者类 - 需要被适配的类
/// </summary>
public class Adaptee
{/// <summary>/// 适配者的特殊请求方法/// </summary>public string SpecificRequest(){return "特殊请求";}
}/// <summary>
/// 对象适配器 - 通过组合使用适配者
/// </summary>
public class Adapter : ITarget
{private readonly Adaptee _adaptee;public Adapter(Adaptee adaptee){_adaptee = adaptee;}/// <summary>/// 实现目标接口,但内部调用适配者的方法/// </summary>public string Request(){// 这里可以进行一些转换工作return $"适配者的工作: {_adaptee.SpecificRequest()}";}
}// 使用示例
public class Program
{public static void Main(){// 创建适配者实例Adaptee adaptee = new Adaptee();// 创建适配器并传入适配者ITarget target = new Adapter(adaptee);// 客户端通过目标接口调用适配器Console.WriteLine("适配者说: " + adaptee.SpecificRequest());Console.WriteLine("目标接口说: " + target.Request());}
}
4.2 桥接模式 (Bridge)
桥接模式将抽象部分与其实现部分分离,使它们都可以独立地变化。
C#实现示例:
/// <summary>
/// 实现部分的接口
/// </summary>
public interface IImplementation
{string OperationImplementation();
}/// <summary>
/// 具体实现A
/// </summary>
public class ConcreteImplementationA : IImplementation
{public string OperationImplementation(){return "具体实现A的结果";}
}/// <summary>
/// 具体实现B
/// </summary>
public class ConcreteImplementationB : IImplementation
{public string OperationImplementation(){return "具体实现B的结果";}
}/// <summary>
/// 抽象部分 - 定义抽象部分的接口
/// </summary>
public class Abstraction
{protected IImplementation _implementation;public Abstraction(IImplementation implementation){_implementation = implementation;}public virtual string Operation(){return $"抽象: 基础操作与 {_implementation.OperationImplementation()}";}
}/// <summary>
/// 扩展的抽象 - 扩展抽象部分的接口
/// </summary>
public class ExtendedAbstraction : Abstraction
{public ExtendedAbstraction(IImplementation implementation) : base(implementation){}public override string Operation(){return $"扩展抽象: 扩展操作与 {_implementation.OperationImplementation()}";}
}// 使用示例
public class Program
{public static void Main(){// 创建实现IImplementation implementationA = new ConcreteImplementationA();IImplementation implementationB = new ConcreteImplementationB();// 将抽象与实现组合在一起Abstraction abstraction = new Abstraction(implementationA);Console.WriteLine(abstraction.Operation());// 改变实现abstraction = new Abstraction(implementationB);Console.WriteLine(abstraction.Operation());// 使用扩展抽象ExtendedAbstraction extendedAbstraction = new ExtendedAbstraction(implementationA);Console.WriteLine(extendedAbstraction.Operation());extendedAbstraction = new ExtendedAbstraction(implementationB);Console.WriteLine(extendedAbstraction.Operation());}
}
4.3 组合模式 (Composite)
组合模式将对象组合成树形结构,以表示"部分-整体"的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
C#实现示例:
using System;
using System.Collections.Generic;/// <summary>
/// 组件接口 - 组合中所有对象的通用接口
/// </summary>
public abstract class Component
{protected string name;public Component(string name){this.name = name;}/// <summary>/// 基本操作,所有组件必须实现/// </summary>public abstract string Operation();/// <summary>/// 添加组件的方法,默认实现是抛出异常/// </summary>public virtual void Add(Component component){throw new NotImplementedException();}/// <summary>/// 移除组件的方法,默认实现是抛出异常/// </summary>public virtual void Remove(Component component){throw new NotImplementedException();}/// <summary>/// 是否是复合组件/// </summary>public virtual bool IsComposite(){return false;}
}/// <summary>
/// 叶子节点 - 组合中的终端对象,没有子节点
/// </summary>
public class Leaf : Component
{public Leaf(string name) : base(name){}public override string Operation(){return $"叶子 {name}";}
}/// <summary>
/// 复合组件 - 可以包含子组件的组件
/// </summary>
public class Composite : Component
{protected List<Component> _children = new List<Component>();public Composite(string name) : base(name){}/// <summary>/// 添加子组件/// </summary>public override void Add(Component component){_children.Add(component);}/// <summary>/// 移除子组件/// </summary>public override void Remove(Component component){_children.Remove(component);}/// <summary>/// 执行组件操作,通常会递归调用所有子组件的操作/// </summary>public override string Operation(){int i = 0;string result = $"分支 {name} (";foreach (var component in _children){result += component.Operation();if (i != _children.Count - 1){result += " + ";}i++;}return result + ")";}public override bool IsComposite(){return true;}
}// 使用示例
public class Program
{public static void Main(){// 创建树形结构// 创建根节点Component root = new Composite("Root");// 创建分支节点Component branch1 = new Composite("Branch 1");Component branch2 = new Composite("Branch 2");// 创建叶子节点Component leaf1 = new Leaf("Leaf 1");Component leaf2 = new Leaf("Leaf 2");Component leaf3 = new Leaf("Leaf 3");// 组装树形结构branch1.Add(leaf1);branch1.Add(leaf2);branch2.Add(leaf3);root.Add(branch1);root.Add(branch2);// 直接使用根节点Console.WriteLine("使用根节点:");Console.WriteLine(root.Operation());// 使用分支节点Console.WriteLine("\n使用分支节点:");Console.WriteLine(branch1.Operation());// 使用叶子节点Console.WriteLine("\n使用叶子节点:");Console.WriteLine(leaf1.Operation());}
}
4.4 装饰器模式 (Decorator)
装饰器模式动态地给一个对象添加一些额外的职责,比继承更灵活。
C#实现示例:
/// <summary>
/// 组件接口 - 定义装饰器和被装饰对象的公共接口
/// </summary>
public interface IComponent
{string Operation();
}/// <summary>
/// 具体组件 - 定义一个可以被装饰的对象
/// </summary>
public class ConcreteComponent : IComponent
{public string Operation(){return "具体组件结果";}
}/// <summary>
/// 装饰器基类 - 维护一个对组件对象的引用
/// </summary>
public abstract class Decorator : IComponent
{protected IComponent _component;public Decorator(IComponent component){_component = component;}// 装饰器将操作委托给组件public virtual string Operation(){return _component.Operation();}
}/// <summary>
/// 具体装饰器A - 向组件添加责任
/// </summary>
public class ConcreteDecoratorA : Decorator
{public ConcreteDecoratorA(IComponent component) : base(component){}// 在被装饰组件的操作前后添加自己的行为public override string Operation(){return $"具体装饰器A({base.Operation()})";}
}/// <summary>
/// 具体装饰器B - 向组件添加责任
/// </summary>
public class ConcreteDecoratorB : Decorator
{public ConcreteDecoratorB(IComponent component) : base(component){}// 在被装饰组件的操作前后添加自己的行为public override string Operation(){return $"具体装饰器B({base.Operation()})";}// 装饰器B特有的方法public string AddedBehavior(){return "添加的行为";}
}// 使用示例
public class Program
{public static void Main(){// 创建一个简单组件IComponent simple = new ConcreteComponent();Console.WriteLine("简单组件结果:");Console.WriteLine(simple.Operation());// 用装饰器A装饰它IComponent decorator1 = new ConcreteDecoratorA(simple);Console.WriteLine("\n使用装饰器A的结果:");Console.WriteLine(decorator1.Operation());// 用装饰器B装饰装饰器AIComponent decorator2 = new ConcreteDecoratorB(decorator1);Console.WriteLine("\n使用装饰器B包装装饰器A的结果:");Console.WriteLine(decorator2.Operation());// 可以直接嵌套多个装饰器IComponent decorator3 = new ConcreteDecoratorB(new ConcreteDecoratorA(new ConcreteComponent()));Console.WriteLine("\n使用嵌套装饰器的结果:");Console.WriteLine(decorator3.Operation());}
}
4.5 外观模式 (Facade)
外观模式为子系统中的一组接口提供一个一致的界面,使得子系统更加容易使用。
C#实现示例:
/// <summary>
/// 子系统1 - 复杂子系统的一部分
/// </summary>
public class Subsystem1
{public string Operation1(){return "子系统1: 准备就绪!";}public string OperationN(){return "子系统1: 开始运行!";}
}/// <summary>
/// 子系统2 - 复杂子系统的一部分
/// </summary>
public class Subsystem2
{public string Operation1(){return "子系统2: 准备就绪!";}public string OperationZ(){return "子系统2: 开始运行!";}
}/// <summary>
/// 外观 - 提供简单接口访问复杂子系统
/// </summary>
public class Facade
{protected Subsystem1 _subsystem1;protected Subsystem2 _subsystem2;/// <summary>/// 外观可以接受已有的子系统对象或创建新的子系统对象/// </summary>public Facade(Subsystem1 subsystem1 = null, Subsystem2 subsystem2 = null){_subsystem1 = subsystem1 ?? new Subsystem1();_subsystem2 = subsystem2 ?? new Subsystem2();}/// <summary>/// 外观提供简单的接口来运行复杂的子系统/// </summary>public string Operation(){string result = "外观初始化子系统:\n";result += _subsystem1.Operation1();result += "\n" + _subsystem2.Operation1();result += "\n外观命令子系统执行操作:\n";result += _subsystem1.OperationN();result += "\n" + _subsystem2.OperationZ();return result;}
}// 使用示例
public class Program
{public static void Main(){// 外观可以与已存在的子系统一起工作Subsystem1 subsystem1 = new Subsystem1();Subsystem2 subsystem2 = new Subsystem2();Facade facade = new Facade(subsystem1, subsystem2);Console.WriteLine(facade.Operation());// 外观可以创建并配置子系统Facade facade2 = new Facade();Console.WriteLine("\n使用自动创建的子系统:");Console.WriteLine(facade2.Operation());}
}
4.6 享元模式 (Flyweight)
享元模式通过共享尽可能多的相似对象来最小化内存使用和对象创建的开销。
C#实现示例:
using System;
using System.Collections.Generic;/// <summary>
/// 享元接口 - 定义享元对象接受外部状态的方法
/// </summary>
public interface IFlyweight
{void Operation(string extrinsicState);
}/// <summary>
/// 具体享元 - 存储内部状态并实现享元接口
/// </summary>
public class ConcreteFlyweight : IFlyweight
{private readonly string _intrinsicState;public ConcreteFlyweight(string intrinsicState){_intrinsicState = intrinsicState;}public void Operation(string extrinsicState){Console.WriteLine($"具体享元: 内部状态 = {_intrinsicState}, 外部状态 = {extrinsicState}");}
}/// <summary>
/// 享元工厂 - 创建并管理享元对象
/// </summary>
public class FlyweightFactory
{private Dictionary<string, IFlyweight> _flyweights = new Dictionary<string, IFlyweight>();public FlyweightFactory(){// 初始化一些常用的享元对象_flyweights.Add("X", new ConcreteFlyweight("共享 X"));_flyweights.Add("Y", new ConcreteFlyweight("共享 Y"));_flyweights.Add("Z", new ConcreteFlyweight("共享 Z"));}/// <summary>/// 返回一个现有的享元或创建一个新的享元/// </summary>public IFlyweight GetFlyweight(string key){if (!_flyweights.ContainsKey(key)){Console.WriteLine($"FlyweightFactory: 找不到键为 {key} 的享元,创建新实例。");_flyweights.Add(key, new ConcreteFlyweight($"共享 {key}"));}else{Console.WriteLine($"FlyweightFactory: 重用现有的享元,键为 {key}。");}return _flyweights[key];}/// <summary>/// 列出所有享元/// </summary>public void ListFlyweights(){int count = _flyweights.Count;Console.WriteLine($"\n工厂中的享元数量: {count}");foreach (var key in _flyweights.Keys){Console.WriteLine(key);}}
}// 使用示例
public class Program
{public static void Main(){// 客户端代码通常会创建一堆预初始化的享元var factory = new FlyweightFactory();factory.ListFlyweights();// 使用现有的享元Console.WriteLine("\n使用现有的享元:");IFlyweight fx = factory.GetFlyweight("X");fx.Operation("客户端外部状态A");// 重用现有的享元Console.WriteLine("\n重用现有的享元:");IFlyweight fy = factory.GetFlyweight("Y");fy.Operation("客户端外部状态B");// 创建新的享元Console.WriteLine("\n创建新的享元:");IFlyweight fw = factory.GetFlyweight("W");fw.Operation("客户端外部状态C");factory.ListFlyweights();}
}
4.7 代理模式 (Proxy)
代理模式为另一个对象提供一个替身或占位符,以控制对这个对象的访问。
C#实现示例:
/// <summary>
/// 主题接口 - 代理和实际主题共同的接口
/// </summary>
public interface ISubject
{void Request();
}/// <summary>
/// 实际主题 - 定义代理所代表的真实对象
/// </summary>
public class RealSubject : ISubject
{public void Request(){Console.WriteLine("RealSubject: 处理请求");}
}/// <summary>
/// 代理 - 保存一个引用,使代理可以访问实际主题
/// </summary>
public class Proxy : ISubject
{private RealSubject _realSubject;/// <summary>/// 根据需要创建或使用已有的实际主题/// </summary>public Proxy(RealSubject realSubject = null){_realSubject = realSubject ?? new RealSubject();}/// <summary>/// 代理的请求方法可以在转发调用前后执行附加工作/// </summary>public void Request(){if (CheckAccess()){// 可以在调用RealSubject之前做一些事情_realSubject.Request();// 可以在调用RealSubject之后做一些事情LogAccess();}}/// <summary>/// 检查是否允许访问实际主题/// </summary>private bool CheckAccess(){// 这里可以有一些真实的检查逻辑Console.WriteLine("Proxy: 检查访问权限");return true;}/// <summary>/// 记录对实际主题的访问/// </summary>private void LogAccess(){Console.WriteLine("Proxy: 记录访问时间");}
}// 使用示例
public class Program
{public static void Main(){Console.WriteLine("客户端: 直接使用实际主题");RealSubject realSubject = new RealSubject();realSubject.Request();Console.WriteLine("\n客户端: 通过代理使用实际主题");Proxy proxy = new Proxy();proxy.Request();}
}
5. 行为型设计模式
行为型设计模式关注对象之间的通信和责任分配。它们帮助定义对象之间通信的方式,以及不同对象间如何协作以完成特定任务。
5.1 观察者模式 (Observer)
观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
C#实现示例:
using System;
using System.Collections.Generic;/// <summary>
/// 主题接口 - 定义添加、删除和通知观察者的操作
/// </summary>
public interface ISubject
{void Attach(IObserver observer);void Detach(IObserver observer);void Notify();
}/// <summary>
/// 观察者接口 - 定义更新方法
/// </summary>
public interface IObserver
{void Update(ISubject subject);
}/// <summary>
/// 具体主题 - 维护状态并通知观察者变化
/// </summary>
public class ConcreteSubject : ISubject
{// 状态,当它改变时通知观察者private string _state;// 观察者列表private List<IObserver> _observers = new List<IObserver>();// 状态属性public string State{get { return _state; }set{_state = value;// 状态变化时通知观察者Notify();}}// 添加观察者public void Attach(IObserver observer){Console.WriteLine("主题: 添加一个观察者");_observers.Add(observer);}// 移除观察者public void Detach(IObserver observer){_observers.Remove(observer);Console.WriteLine("主题: 移除一个观察者");}// 通知所有观察者public void Notify(){Console.WriteLine("主题: 通知观察者...");foreach (var observer in _observers){observer.Update(this);}}// 一些业务逻辑public void SomeBusinessLogic(){Console.WriteLine("\n主题: 我在做一些重要的事情");this.State = $"状态已更改为: {DateTime.Now}";}
}/// <summary>
/// 具体观察者A - 实现更新接口
/// </summary>
public class ConcreteObserverA : IObserver
{public void Update(ISubject subject){if (subject is ConcreteSubject concreteSubject){Console.WriteLine($"具体观察者A: 对新状态做出反应: {concreteSubject.State}");}}
}/// <summary>
/// 具体观察者B - 实现更新接口
/// </summary>
public class ConcreteObserverB : IObserver
{public void Update(ISubject subject){if (subject is ConcreteSubject concreteSubject){Console.WriteLine($"具体观察者B: 对新状态做出反应: {concreteSubject.State}");}}
}// 使用示例
public class Program
{public static void Main(){// 创建主题var subject = new ConcreteSubject();// 创建观察者var observerA = new ConcreteObserverA();var observerB = new ConcreteObserverB();// 订阅subject.Attach(observerA);subject.Attach(observerB);// 改变状态subject.SomeBusinessLogic();// 取消订阅subject.Detach(observerB);// 再次改变状态subject.SomeBusinessLogic();}
}
5.2 策略模式 (Strategy)
策略模式定义一系列算法,将每个算法封装起来,并使它们可以相互替换。此模式使得算法可以独立于使用它的客户而变化。
C#实现示例:
/// <summary>
/// 策略接口 - 定义算法族的共同接口
/// </summary>
public interface IStrategy
{string Execute(string data);
}/// <summary>
/// 具体策略A - 定义具体算法
/// </summary>
public class ConcreteStrategyA : IStrategy
{public string Execute(string data){// 具体算法A的实现return $"使用策略A处理数据: {data.ToUpper()}";}
}/// <summary>
/// 具体策略B - 定义具体算法
/// </summary>
public class ConcreteStrategyB : IStrategy
{public string Execute(string data){// 具体算法B的实现return $"使用策略B处理数据: {new string(data.ToCharArray().Reverse().ToArray())}";}
}/// <summary>
/// 具体策略C - 定义具体算法
/// </summary>
public class ConcreteStrategyC : IStrategy
{public string Execute(string data){// 具体算法C的实现return $"使用策略C处理数据: {string.Join(" ", data.ToCharArray())}";}
}/// <summary>
/// 上下文 - 维护对策略对象的引用
/// </summary>
public class Context
{// 当前使用的策略private IStrategy _strategy;// 可以在构造函数中设置初始策略public Context(IStrategy strategy = null){_strategy = strategy;}// 允许在运行时更改策略public void SetStrategy(IStrategy strategy){_strategy = strategy;}// 委托策略执行算法public string ExecuteStrategy(string data){if (_strategy == null){return "未设置策略";}return _strategy.Execute(data);}
}// 使用示例
public class Program
{public static void Main(){// 创建上下文var context = new Context();// 设置并执行策略Acontext.SetStrategy(new ConcreteStrategyA());Console.WriteLine(context.ExecuteStrategy("Hello, World!"));// 改变策略为Bcontext.SetStrategy(new ConcreteStrategyB());Console.WriteLine(context.ExecuteStrategy("Hello, World!"));// 改变策略为Ccontext.SetStrategy(new ConcreteStrategyC());Console.WriteLine(context.ExecuteStrategy("Hello, World!"));}
}
5.3 模板方法模式 (Template Method)
模板方法模式在一个方法中定义一个算法的骨架,将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的特定步骤。
C#实现示例:
/// <summary>
/// 抽象类 - 定义算法骨架
/// </summary>
public abstract class AbstractClass
{// 模板方法,定义算法的骨架public void TemplateMethod(){Console.WriteLine("AbstractClass: 算法已开始");PrimitiveOperation1();PrimitiveOperation2();Hook();Console.WriteLine("AbstractClass: 算法已结束");}// 原始操作1 - 必须由子类实现protected abstract void PrimitiveOperation1();// 原始操作2 - 必须由子类实现protected abstract void PrimitiveOperation2();// 钩子方法 - 子类可以选择性地覆盖protected virtual void Hook() { }
}/// <summary>
/// 具体类A - 实现原始操作
/// </summary>
public class ConcreteClassA : AbstractClass
{protected override void PrimitiveOperation1(){Console.WriteLine("ConcreteClassA: 实现操作1");}protected override void PrimitiveOperation2(){Console.WriteLine("ConcreteClassA: 实现操作2");}
}/// <summary>
/// 具体类B - 实现原始操作并覆盖钩子
/// </summary>
public class ConcreteClassB : AbstractClass
{protected override void PrimitiveOperation1(){Console.WriteLine("ConcreteClassB: 实现操作1");}protected override void PrimitiveOperation2(){Console.WriteLine("ConcreteClassB: 实现操作2");}// 覆盖钩子方法protected override void Hook(){Console.WriteLine("ConcreteClassB: 覆盖了钩子方法");}
}// 使用示例
public class Program
{public static void Main(){Console.WriteLine("使用具体类A:");AbstractClass abstractClass = new ConcreteClassA();abstractClass.TemplateMethod();Console.WriteLine("\n使用具体类B:");abstractClass = new ConcreteClassB();abstractClass.TemplateMethod();}
}
5.4 命令模式 (Command)
命令模式将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
C#实现示例:
using System;
using System.Collections.Generic;/// <summary>
/// 命令接口 - 声明执行和撤销操作
/// </summary>
public interface ICommand
{void Execute();void Undo();
}/// <summary>
/// 接收者 - 知道如何执行与命令相关的操作
/// </summary>
public class Receiver
{public void Action(string action){Console.WriteLine($"接收者: 执行 {action}");}
}/// <summary>
/// 具体命令 - 将接收者和动作绑定在一起
/// </summary>
public class ConcreteCommand : ICommand
{private readonly Receiver _receiver;private readonly string _action;public ConcreteCommand(Receiver receiver, string action){_receiver = receiver;_action = action;}// 调用接收者的相关操作public void Execute(){Console.WriteLine($"命令: 调用接收者执行 {_action}");_receiver.Action(_action);}// 撤销操作public void Undo(){Console.WriteLine($"命令: 撤销接收者的 {_action}");_receiver.Action($"撤销 {_action}");}
}/// <summary>
/// 调用者 - 请求命令执行请求
/// </summary>
public class Invoker
{private ICommand _command;// 设置要执行的命令public void SetCommand(ICommand command){_command = command;}// 执行命令public void ExecuteCommand(){if (_command != null){Console.WriteLine("调用者: 执行命令");_command.Execute();}}// 撤销命令public void UndoCommand(){if (_command != null){Console.WriteLine("调用者: 撤销命令");_command.Undo();}}
}// 使用示例
public class Program
{public static void Main(){// 创建接收者var receiver = new Receiver();// 创建命令并绑定接收者var command = new ConcreteCommand(receiver, "某个行动");// 创建调用者并设置命令var invoker = new Invoker();invoker.SetCommand(command);// 执行和撤销命令invoker.ExecuteCommand();invoker.UndoCommand();}
}
5.5 迭代器模式 (Iterator)
迭代器模式提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
C#实现示例:
using System;
using System.Collections;
using System.Collections.Generic;/// <summary>
/// 迭代器接口 - 在C#中通常使用内置的IEnumerable和IEnumerator接口
/// </summary>
public interface ICustomIterator<T>
{bool MoveNext();void Reset();T Current { get; }
}/// <summary>
/// 集合接口 - 在C#中通常使用内置的IEnumerable接口
/// </summary>
public interface ICustomCollection<T>
{ICustomIterator<T> CreateIterator();
}/// <summary>
/// 具体集合 - 存储元素并创建迭代器
/// </summary>
public class ConcreteCollection<T> : ICustomCollection<T>
{private List<T> _items = new List<T>();// 添加项public void AddItem(T item){_items.Add(item);}// 创建迭代器public ICustomIterator<T> CreateIterator(){return new ConcreteIterator<T>(this);}// 获取项数量public int Count{get { return _items.Count; }}// 通过索引访问项public T this[int index]{get { return _items[index]; }}
}/// <summary>
/// 具体迭代器 - 实现迭代接口
/// </summary>
public class ConcreteIterator<T> : ICustomIterator<T>
{private readonly ConcreteCollection<T> _collection;private int _current = 0;public ConcreteIterator(ConcreteCollection<T> collection){_collection = collection;}// 移动到下一项public bool MoveNext(){return ++_current < _collection.Count;}// 重置迭代器public void Reset(){_current = 0;}// 获取当前项public T Current{get { return _collection[_current]; }}
}/// <summary>
/// 使用C#内置集合接口的集合
/// </summary>
public class BuiltInCollection<T> : IEnumerable<T>
{private List<T> _items = new List<T>();// 添加项public void AddItem(T item){_items.Add(item);}// 实现IEnumerable接口public IEnumerator<T> GetEnumerator(){return _items.GetEnumerator();}// 显式实现IEnumerable接口IEnumerator IEnumerable.GetEnumerator(){return GetEnumerator();}
}// 使用示例
public class Program
{public static void Main(){// 使用自定义迭代器接口Console.WriteLine("使用自定义迭代器:");var collection = new ConcreteCollection<string>();collection.AddItem("项目 A");collection.AddItem("项目 B");collection.AddItem("项目 C");var iterator = collection.CreateIterator();// 手动迭代Console.WriteLine(iterator.Current);while (iterator.MoveNext()){Console.WriteLine(iterator.Current);}// 使用C#内置集合接口Console.WriteLine("\n使用C#内置集合接口:");var builtInCollection = new BuiltInCollection<string>();builtInCollection.AddItem("项目 X");builtInCollection.AddItem("项目 Y");builtInCollection.AddItem("项目 Z");// 使用foreach语法糖自动迭代foreach (var item in builtInCollection){Console.WriteLine(item);}}
}
5.6 状态模式 (State)
状态模式允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
C#实现示例:
/// <summary>
/// 上下文 - 保存当前状态并委托状态相关的行为
/// </summary>
public class Context
{// 当前状态private IState _state;public Context(IState initialState){TransitionTo(initialState);}/// <summary>/// 转换到新状态/// </summary>public void TransitionTo(IState state){Console.WriteLine($"上下文: 转换到 {state.GetType().Name}");_state = state;_state.SetContext(this);}/// <summary>/// 委托行为给当前状态/// </summary>public void Request1(){_state.Handle1();}public void Request2(){_state.Handle2();}
}/// <summary>
/// 状态接口 - 声明与上下文的交互方法
/// </summary>
public interface IState
{void SetContext(Context context);void Handle1();void Handle2();
}/// <summary>
/// 具体状态A
/// </summary>
public class ConcreteStateA : IState
{private Context _context;public void SetContext(Context context){_context = context;}public void Handle1(){Console.WriteLine("ConcreteStateA处理请求1。");// 可以在这里改变上下文的状态}public void Handle2(){Console.WriteLine("ConcreteStateA处理请求2。");Console.WriteLine("ConcreteStateA改变上下文的状态为B。");_context.TransitionTo(new ConcreteStateB());}
}/// <summary>
/// 具体状态B
/// </summary>
public class ConcreteStateB : IState
{private Context _context;public void SetContext(Context context){_context = context;}public void Handle1(){Console.WriteLine("ConcreteStateB处理请求1。");Console.WriteLine("ConcreteStateB改变上下文的状态为A。");_context.TransitionTo(new ConcreteStateA());}public void Handle2(){Console.WriteLine("ConcreteStateB处理请求2。");}
}// 使用示例
public class Program
{public static void Main(){// 创建上下文并设置初始状态var context = new Context(new ConcreteStateA());// 执行请求,会委托给当前状态处理Console.WriteLine("客户端: 执行请求1");context.Request1();Console.WriteLine("\n客户端: 执行请求2");context.Request2();// 上下文已经转换到B状态Console.WriteLine("\n客户端: 执行请求1");context.Request1();// 上下文又回到A状态Console.WriteLine("\n客户端: 执行请求2");context.Request2();}
}
6. 总结与展望
6.1 设计模式的优缺点
设计模式作为软件开发中的最佳实践,具有明显的优点:
- 提高代码质量:设计模式遵循面向对象设计原则,有助于创建松耦合、高内聚的代码
- 加快开发速度:提供了经过验证的解决方案,避免从零开始解决常见问题
- 增强代码维护性:通过标准化和模块化,使代码更易于理解和修改
- 促进团队协作:提供共同的词汇和理解,改善团队沟通
然而,设计模式并非万能,也存在一些潜在的缺点:
- 过度使用:不必要地应用设计模式会增加代码的复杂性
- 性能开销:某些设计模式可能引入额外的抽象层,导致性能下降
- 学习曲线:理解和正确应用设计模式需要时间和经验
- 上下文依赖:设计模式的适用性取决于具体问题和上下文
6.2 选择合适的设计模式
选择正确的设计模式是一项重要的决策,应考虑以下因素:
- 问题特性:理解问题的本质和约束
- 设计目标:明确系统的质量属性(可扩展性、可维护性等)
- 权衡取舍:考虑模式的优缺点与当前需求的匹配度
- 团队经验:考虑团队对特定模式的熟悉程度
- 系统上下文:考虑与现有系统架构的兼容性
6.3 设计模式的演进
设计模式并非静态不变,它们随着技术和范式的变化而演进:
- 函数式编程的普及带来了新的设计模式和对传统模式的重新诠释
- 微服务架构催生了分布式系统特有的设计模式
- 响应式编程引入了处理异步数据流的新模式
- 领域驱动设计融合了多种设计模式,形成了更高层次的架构模式
6.4 学习资源
以下是深入学习设计模式的优质资源:
在线资源:
- Refactoring.Guru - 设计模式的详细解释和代码示例
- Microsoft Learn - .NET架构原则和设计模式
- SourceMaking - 设计模式、反模式和重构
- dofactory - .NET设计模式示例和实践
社区和论坛:
- Stack Overflow
- GitHub
- Reddit r/csharp
7. 结语
设计模式是软件开发中不可或缺的知识体系,尤其对于C#这样成熟的面向对象语言来说更是如此。深入理解和正确应用设计模式,能够帮助开发者创建更加灵活、可维护的软件系统。
然而,设计模式不应被视为教条,而应作为工具和指导原则。最重要的是理解问题的本质和设计原则,然后选择或调整适当的模式来解决特定问题。
相关文章:

23种设计模式概述详述(C#代码示例)
文章目录 1. 引言1.1 设计模式的价值1.2 设计模式的分类 2. 面向对象设计原则2.1 单一职责原则 (SRP)2.2 开放封闭原则 (OCP)2.3 里氏替换原则 (LSP)2.4 接口隔离原则 (ISP)2.5 依赖倒置原则 (DIP)2.6 合成复用原则 (CRP)2.7 迪米特法则 (LoD) 3. 创建型设计模式3.1 单例模式 (…...

数字化工厂升级引擎:Modbus TCP转Profinet网关助力打造柔性生产系统
在当今的工业自动化领域,通信协议扮演着至关重要的角色。Modbus TCP和Profinet是两种广泛使用的工业通信协议,它们分别在不同的应用场景中发挥着重要作用。然而,有时我们可能需要将这两种协议进行转换,以实现不同设备之间的无缝通…...

FPGA生成随机数的方法
FPGA生成随机数的方法,目前有以下几种: 1、震荡采样法 实现方式一:通过低频时钟作为D触发器的时钟输入端,高频时钟作为D触发器的数据输入端,使用高频采样低频,利用亚稳态输出随机数。 实现方式二:使用三个…...

【Linux C/C++开发】轻量级关系型数据库SQLite开发(包含性能测试代码)
前言 之前的文件分享过基于内存的STL缓存、环形缓冲区,以及基于文件的队列缓存mqueue、hash存储、向量库annoy存储,这两种属于比较原始且高效的方式。 那么,有没有高级且高效的方式呢。有的,从数据角度上看,࿰…...
2025认证杯第二阶段数学建模B题:谣言在社交网络上的传播思路+模型+代码
2025认证杯数学建模第二阶段思路模型代码,详细内容见文末名片 一、引言 在当今数字化时代,社交网络已然成为人们生活中不可或缺的一部分。信息在社交网络上的传播速度犹如闪电,瞬间就能触及大量用户。然而,这也为谣言的滋生和扩…...

记录算法笔记(2025.5.17)验证二叉搜索树
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 1: 输入&…...

flutter编译时 设置jdk版本
先查看flutter使用的版本 flutter doctor -v设置flutter的jdk目录 flutter config --jdk-dir "E:\soft\android-studio\jbr" 然后再验证下,看是否设置成功...

ctfshow——web入门254~258
目录 web入门254 web入门255 web入门256 web入门257 web入门258 反序列化 先来看看其他师傅的讲解 web入门254 源码: <?phperror_reporting(0); highlight_file(__FILE__); include(flag.php);class ctfShowUser{public $usernamexxxxxx;public $passwo…...

【数据处理】xarray 数据处理教程:从入门到精通
目录 xarray 数据处理教程:从入门到精通一、简介**核心优势** 二、安装与导入1. 安装2. 导入库 三、数据结构(一)DataArray(二) Dataset(三)关键说明 四、数据操作(一)索…...

qt5.14.2 opencv调用摄像头显示在label
ui界面添加一个Qlabel名字是默认的label 还有一个button名字是pushButton mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <opencv2/opencv.hpp> // 添加OpenCV头文件 #include <QTimer> // 添加定…...
科技的成就(六十八)
623、杰文斯悖论 杰文斯悖论是1865年经济学家威廉斯坦利杰文斯提出的一悖论:当技术进步提高了效率,资源消耗不仅没有减少,反而激增。例如,瓦特改良的蒸汽机让煤炭燃烧更加高效,但结果却是煤炭需求飙升。 624、代码混…...

芯片生态链深度解析(三):芯片设计篇——数字文明的造物主战争
【开篇:设计——数字文明的“造物主战场”】 当英伟达的H100芯片以576TB/s显存带宽重构AI算力边界,当阿里平头哥倚天710以RISC-V架构实现性能对标ARM的突破,这场围绕芯片设计的全球竞赛早已超越技术本身,成为算法、架构与生态标准…...

Rocky Linux 9.5 基于kubeadm部署k8s
一:部署说明 操作系统https://mirrors.aliyun.com/rockylinux/9.5/isos/x86_64/Rocky-9.5-x86_64-minimal.iso 主机名IP地址配置k8s- master192.168.1.1412颗CPU 4G内存 100G硬盘k8s- node-1192.168.1.1422颗CPU 4G内存 100G硬盘k8s- node-2192.168.1.1432…...
--openssl-legacy-provider is not allowed in NODE_OPTIONS 报错的处理方式
解决方案 Node.js 应用: 从 Node.js v17 开始,底层升级到 OpenSSL 3.0,可能导致旧代码报错(如 ERR_OSSL_EVP_UNSUPPORTED)。 通过以下命令启用旧算法支持: node --openssl-legacy-provider your_script.js…...

uart16550详细说明
一、介绍 uart16550 ip core异步串行通信IP连接高性能的微控制器总线AXI,并为异步串行通信提供了 控制接口。软核设计连接了axilite接口。 二、特性 1.axilite接口用于寄存器访问和数据传输 2.16650串口和16450串口的软件和硬件寄存器都是兼容的 3.默认的core配置参数…...
deepin v23.1 音量自动静音问题解决
有的机器上会有音量自动静音问题, 如果你的电脑上也遇到, 这个问题是 Linux 内核的原因, ubuntu上也可能会遇到相同问题(比如你升级了最新内核6.14), 而我测试得6.8.0的内核是不会自动静音的. Index of /mainline 到上面这个链接(linux 内核的官方链接)下载6.8.0的内核, s…...

抢跑「中央计算+区域控制」市场,芯驰科技高端智控MCU“芯”升级
伴随着整车EE架构的加速变革,中国高端车规MCU正在迎来“新格局”。 在4月23日开幕的上海国际车展期间,芯驰科技面向新一代AI座舱推出了X10系列芯片,以及面向区域控制器、电驱和动力域控、高阶辅助驾驶和舱驾融合系统等的高端智控MCU产品E3系…...
《算法导论(第4版)》阅读笔记:p82-p82
《算法导论(第4版)》学习第 17 天,p82-p82 总结,总计 1 页。 一、技术总结 1. Matrix Matrices(矩阵) (1)教材 因为第 4 章涉及到矩阵,矩阵属于线性代数(linear algebra)范畴,如果不熟悉,可以看一下作者推荐的两本…...

day015-进程管理
文章目录 1. 服务开机自启动2. 进程3. 僵尸进程3.1 处理僵尸进程3.2 查看僵尸进程3.2 排查与结束僵尸进程全流程 4. 孤儿进程5. 进程管理5.1 kill三剑客5.2 后台运行 6. 进程监控命令6.1 ps6.1.1 ps -ef6.1.2 ps aux6.1.3 VSZ、RSS6.1.4 进程状态6.1.5 进程、线程 6.2 top6.2.1…...
traceroute命令: -g与-i 参数
[rootwww ~]# traceroute [选项与参数] IP 选项与参数:-i 装置:用在比较复杂的环境,如果你的网络接口很多很复杂时,才会用到这个参数;*举例来说,你有两条 ADSL 可以连接到外部,那你的主机会有两…...

POWER BI添加自定义字体
POWER BI添加自定义字体 POWER BI内置27种字体,今天分享一种很简单的添加自定义字体的方法。以更改如下pbix文件字体为例: 第一步:将该pbix文件重命名为zip文件并解压,找到主题json文件,如下图所示: 第二步…...
SpringAI更新:废弃tools方法、正式支持DeepSeek!
AI 技术发展很快,同样 AI 配套的相关技术发展也很快。这不今天刚打开 Spring AI 的官网就发现它又又又又更新了,而这次更新距离上次更新 M7 版本才不过半个月的时间,那这次 Spring AI 给我们带来了哪些惊喜呢?一起来看。 重点升级…...

协议不兼容?Profinet转Modbus TCP网关让恒压供水系统通信0障碍
在现代工业自动化领域中,通信协议扮演着至关重要的角色。ModbusTCP和Profinet是两种广泛使用的工业通信协议,它们各自在不同的应用场合中展现出独特的优势。本文将探讨如何通过开疆智能Profinet转Modbus TCP的网关,在恒压供水系统中实现高效的…...

ChatGPT + DeepSeek 联合润色的 Prompt 模板指令合集,用来润色SCI论文太香了!
对于非英语母语的作者来说,写SCI论文的时候经常会碰到语法错误、表达不够专业、结构不清晰以及术语使用不准确等问题。传统的润色方式要么成本高、效率低,修改过程又耗时又费力。虽然AI工具可以帮助我们来润色论文,但单独用ChatGPT或DeepSeek都会存在内容泛泛、专业性不足的…...

全栈项目搭建指南:Nuxt.js + Node.js + MongoDB
全栈项目搭建指南:Nuxt.js Node.js MongoDB 一、项目概述 我们将构建一个完整的全栈应用,包含: 前端:Nuxt.js (SSR渲染)后端:Node.js (Express/Koa框架)数据库:MongoDB后台管理系统:集成在同…...

RAGFlow Arbitrary Account Takeover Vulnerability
文章目录 RAGFlowVulnerability Description[1]Vulnerability Steps[2]Vulnerability Steps[3]Vulnerability Steps RAGFlow RAGFlow is an open-source RAG (Retrieval-Augmented Generation) engine developed by Infiniflow, focused on deep document understanding and d…...

Python 之 Flask 入门学习
安装 Flask 在开始使用 Flask 之前,需要先安装它。可以通过 pip 命令来安装 Flask: pip install Flask创建第一个 Flask 应用 创建一个简单的 Flask 应用,只需要几行代码。以下是一个最基本的 Flask 应用示例: from flask imp…...
微服务,服务粒度多少合适
项目服务化好处 复用性,消除代码拷贝专注性,防止复杂性扩散解耦合,消除公共库耦合高质量,SQL稳定性有保障易扩展,消除数据库解耦合高效率,调用方研发效率提升 微服务拆分实现策略 统一服务层一个子业务一…...

【Ragflow】22.RagflowPlus(v0.3.0):用户会话管理/文件类型拓展/诸多优化更新
概述 在历经三周的阶段性开发后,RagflowPlus顺利完成既定计划,正式发布v0.3.0版本。 开源地址:https://github.com/zstar1003/ragflow-plus 新功能 1. 用户会话管理 在后台管理系统中,新增用户会话管理菜单。在此菜单中&…...

使用PocketFlow构建Web Search Agent
前言 本文介绍的是PocketFlow的cookbook中的pocketflow-agent部分。 回顾一下PocketFlow的核心架构: 每一个节点的架构: 具体介绍可以看上一篇文章: “Pocket Flow,一个仅用 100 行代码实现的 LLM 框架” 实现效果 这个Web S…...