翼度科技»论坛 编程开发 .net 查看内容

使用c#实现23种常见的设计模式

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
使用c#实现23种常见的设计模式

设计模式通常分为三个主要类别:

  • 创建型模式
  • 结构型模式
  • 行为型模式。
这些模式是用于解决常见的对象导向设计问题的最佳实践。
以下是23种常见的设计模式并且提供c#代码案例:
创建型模式:

1. 单例模式(Singleton)
  1. public sealed class Singleton
  2. {
  3.     //创建一个只读的静态Singleton实例
  4.     private static readonly Singleton instance = new Singleton();
  5.     // 记录Singleton的创建次数
  6.     private static int instanceCounter = 0;
  7.     // 单例实例的公共访问点
  8.     public static Singleton Instance
  9.     {
  10.         get
  11.         {
  12.             return instance;
  13.         }
  14.     }
  15.     // 私有构造函数
  16.     private Singleton()
  17.     {
  18.         instanceCounter++;
  19.         Console.WriteLine("Instances Created " + instanceCounter);
  20.     }
  21.     // 在此处添加其他的Singleton类方法
  22.     public void LogMessage(string message)
  23.     {
  24.         Console.WriteLine("Message: " + message);
  25.     }
  26. }
复制代码
在这个例子中,我们有一个名为Singleton的类,它有一个私有的构造函数和一个静态的只读属性Instance,用于访问Singleton类的唯一实例。我们还有一个LogMessage方法,用于模拟Singleton类的某个行为。
以下是一个使用这个Singleton类的控制台应用程序:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         Singleton fromEmployee = Singleton.Instance;
  6.         fromEmployee.LogMessage("Message from Employee");
  7.         Singleton fromBoss = Singleton.Instance;
  8.         fromBoss.LogMessage("Message from Boss");
  9.         Console.ReadLine();
  10.     }
  11. }
复制代码
2. 工厂方法模式(Factory Method)

工厂方法模式是一种创建型设计模式,它提供了一种创建对象的接口,但允许子类决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。
下面是一个使用C#实现的工厂方法模式的简单示例:
  1. // 抽象产品
  2. public interface IProduct
  3. {
  4.     string Operation();
  5. }
  6. // 具体产品A
  7. public class ProductA : IProduct
  8. {
  9.     public string Operation()
  10.     {
  11.         return "{Result of ProductA}";
  12.     }
  13. }
  14. // 具体产品B
  15. public class ProductB : IProduct
  16. {
  17.     public string Operation()
  18.     {
  19.         return "{Result of ProductB}";
  20.     }
  21. }
  22. // 抽象创建者
  23. public abstract class Creator
  24. {
  25.     public abstract IProduct FactoryMethod();
  26. }
  27. // 具体创建者A
  28. public class CreatorA : Creator
  29. {
  30.     public override IProduct FactoryMethod()
  31.     {
  32.         return new ProductA();
  33.     }
  34. }
  35. // 具体创建者B
  36. public class CreatorB : Creator
  37. {
  38.     public override IProduct FactoryMethod()
  39.     {
  40.         return new ProductB();
  41.     }
  42. }
复制代码
以上代码中定义了两个产品ProductA和ProductB,这两个产品都实现了IProduct接口。接着我们有两个Creator类,CreatorA和CreatorB,它们都继承自抽象基类Creator。CreatorA工厂创建ProductA,CreatorB工厂创建ProductB。
以下是一个使用这些工厂和产品的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         // 创建工厂对象
  6.         Creator creatorA = new CreatorA();
  7.         Creator creatorB = new CreatorB();
  8.         // 通过工厂方法创建产品对象
  9.         IProduct productA = creatorA.FactoryMethod();
  10.         IProduct productB = creatorB.FactoryMethod();
  11.         // 打印结果
  12.         Console.WriteLine("ProductA says: " + productA.Operation());
  13.         Console.WriteLine("ProductB says: " + productB.Operation());
  14.         Console.ReadLine();
  15.     }
  16. }
复制代码
当你运行这个程序时,它会显示出ProductA和ProductB的Operation方法返回的结果。这说明我们已经成功地使用工厂方法模式创建了产品实例。每个工厂类决定了它创建哪个产品的实例。这种方式使得客户端代码不需要直接实例化产品类,而只需要依赖工厂接口,增加了程序的灵活性。
3. 抽象工厂模式(Abstract Factory)

抽象工厂模式是一种创建型设计模式,它提供了一种接口,用于创建相关或依赖对象的系列,而不指定这些对象的具体类。在这个模式中,客户端通过他们的抽象接口使用类,允许该模式在不影响客户端的情况下替换实现类。
以下是一个简单的抽象工厂模式的C#实现:
  1. // 抽象产品:动物
  2. public interface IAnimal
  3. {
  4.     string Speak();
  5. }
  6. // 具体产品:狗
  7. public class Dog : IAnimal
  8. {
  9.     public string Speak()
  10.     {
  11.         return "Bark Bark";
  12.     }
  13. }
  14. // 具体产品:猫
  15. public class Cat : IAnimal
  16. {
  17.     public string Speak()
  18.     {
  19.         return "Meow Meow";
  20.     }
  21. }
  22. // 抽象工厂
  23. public abstract class IAnimalFactory
  24. {
  25.     public abstract IAnimal CreateAnimal();
  26. }
  27. // 具体工厂:狗工厂
  28. public class DogFactory : IAnimalFactory
  29. {
  30.     public override IAnimal CreateAnimal()
  31.     {
  32.         return new Dog();
  33.     }
  34. }
  35. // 具体工厂:猫工厂
  36. public class CatFactory : IAnimalFactory
  37. {
  38.     public override IAnimal CreateAnimal()
  39.     {
  40.         return new Cat();
  41.     }
  42. }
复制代码
以上代码定义了两种动物Dog和Cat,它们都实现了IAnimal接口。然后我们有两个工厂类,DogFactory和CatFactory,它们都继承自IAnimalFactory。DogFactory生产Dog,而CatFactory生产Cat。
以下是一个使用这些工厂和产品的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         // 创建工厂
  6.         IAnimalFactory dogFactory = new DogFactory();
  7.         IAnimalFactory catFactory = new CatFactory();
  8.         // 使用工厂创建产品
  9.         IAnimal dog = dogFactory.CreateAnimal();
  10.         IAnimal cat = catFactory.CreateAnimal();
  11.         // 打印结果
  12.         Console.WriteLine("Dog says: " + dog.Speak());
  13.         Console.WriteLine("Cat says: " + cat.Speak());
  14.         Console.ReadLine();
  15.     }
  16. }
复制代码
当你运行这个程序时,会打印出Dog和Cat的Speak方法的结果,这显示了我们已经成功地使用了抽象工厂模式创建了产品实例。这种方式使得客户端代码不需要直接实例化产品类,而只需要依赖工厂接口,增加了程序的灵活性和扩展性。
4. 建造者模式(Builder)

建造者模式是一种创建型设计模式,它提供了一种创建对象的接口,但是允许使用相同的构建过程来创建不同的产品。
以下是在C#中实现建造者模式的一个简单示例:
  1. // 产品
  2. public class Car
  3. {
  4.     public string Engine { get; set; }
  5.     public string Wheels { get; set; }
  6.     public string Doors { get; set; }
  7. }
  8. // 建造者抽象类
  9. public abstract class CarBuilder
  10. {
  11.     protected Car car;
  12.     public void CreateNewCar()
  13.     {
  14.         car = new Car();
  15.     }
  16.     public Car GetCar()
  17.     {
  18.         return car;
  19.     }
  20.     public abstract void SetEngine();
  21.     public abstract void SetWheels();
  22.     public abstract void SetDoors();
  23. }
  24. // 具体建造者
  25. public class FerrariBuilder : CarBuilder
  26. {
  27.     public override void SetEngine()
  28.     {
  29.         car.Engine = "V8";
  30.     }
  31.     public override void SetWheels()
  32.     {
  33.         car.Wheels = "18 inch";
  34.     }
  35.     public override void SetDoors()
  36.     {
  37.         car.Doors = "2";
  38.     }
  39. }
  40. // 指挥者
  41. public class Director
  42. {
  43.     public Car Construct(CarBuilder carBuilder)
  44.     {
  45.         carBuilder.CreateNewCar();
  46.         carBuilder.SetEngine();
  47.         carBuilder.SetWheels();
  48.         carBuilder.SetDoors();
  49.         return carBuilder.GetCar();
  50.     }
  51. }
复制代码
以上代码中,Car是我们要创建的产品,CarBuilder是抽象的建造者,定义了制造一个产品所需要的各个步骤,FerrariBuilder是具体的建造者,实现了CarBuilder定义的所有步骤,Director是指挥者,它告诉建造者应该按照什么顺序去执行哪些步骤。
以下是一个使用这个建造者模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         Director director = new Director();
  6.         CarBuilder builder = new FerrariBuilder();
  7.         Car ferrari = director.Construct(builder);
  8.         Console.WriteLine($"Engine: {ferrari.Engine}, Wheels: {ferrari.Wheels}, Doors: {ferrari.Doors}");
  9.         Console.ReadLine();
  10.     }
  11. }
复制代码
当你运行这个程序时,会看到我们已经成功地创建了一个Car实例,它的各个部分是按照FerrariBuilder所定义的方式创建的。这说明我们使用建造者模式成功地将一个复杂对象的构造过程解耦,使得同样的构造过程可以创建不同的表示。
5. 原型模式(Prototype)

原型模式是一种创建型设计模式,它实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作后被创建。
以下是在C#中实现原型模式的一个简单示例:
  1. // 抽象原型
  2. public interface IPrototype
  3. {
  4.     IPrototype Clone();
  5. }
  6. // 具体原型
  7. public class ConcretePrototype : IPrototype
  8. {
  9.     public string Name { get; set; }
  10.     public int Value { get; set; }
  11.     public IPrototype Clone()
  12.     {
  13.         // 实现深拷贝
  14.         return (ConcretePrototype)this.MemberwiseClone(); // Clones the concrete object.
  15.     }
  16. }
复制代码
以上代码定义了一个ConcretePrototype类,它实现了IPrototype接口。接口定义了一个Clone方法,用于复制对象。在ConcretePrototype类中,我们使用了MemberwiseClone方法来创建一个新的克隆对象。
以下是一个使用原型模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         ConcretePrototype prototype = new ConcretePrototype();
  6.         prototype.Name = "Original";
  7.         prototype.Value = 10;
  8.         Console.WriteLine("Original instance: " + prototype.Name + ", " + prototype.Value);
  9.         ConcretePrototype clone = (ConcretePrototype)prototype.Clone();
  10.         Console.WriteLine("Cloned instance: " + clone.Name + ", " + clone.Value);
  11.         Console.ReadLine();
  12.     }
  13. }
复制代码
在这个例子中,我们创建了一个ConcretePrototype对象,并为其属性赋值,然后我们调用Clone方法创建了一个新的ConcretePrototype对象。当我们运行这个程序时,会看到原始对象和克隆对象的属性是相同的,这表明我们已经成功地克隆了一个对象。
执行流程如下:

  • 创建一个具体的原型对象,为其属性赋值。
  • 调用原型对象的Clone方法,创建一个新的对象,该对象的属性与原型对象的属性相同。
  • 打印原型对象和克隆对象的属性,验证它们是否相同。
结构型模式: 6. 适配器模式(Adapter)

1. 桥接模式(Bridge)

桥接模式是一种结构型设计模式,用于将抽象部分与其实现部分分离,使它们都可以独立地变化。
以下是在C#中实现桥接模式的一个简单示例:
  1. // 实现类接口
  2. public interface IImplementor
  3. {
  4.     void OperationImp();
  5. }
  6. // 具体实现类A
  7. public class ConcreteImplementorA : IImplementor
  8. {
  9.     public void OperationImp()
  10.     {
  11.         Console.WriteLine("Concrete Implementor A");
  12.     }
  13. }
  14. // 具体实现类B
  15. public class ConcreteImplementorB : IImplementor
  16. {
  17.     public void OperationImp()
  18.     {
  19.         Console.WriteLine("Concrete Implementor B");
  20.     }
  21. }
  22. // 抽象类
  23. public abstract class Abstraction
  24. {
  25.     protected IImplementor implementor;
  26.     public Abstraction(IImplementor implementor)
  27.     {
  28.         this.implementor = implementor;
  29.     }
  30.     public virtual void Operation()
  31.     {
  32.         implementor.OperationImp();
  33.     }
  34. }
  35. // 扩充的抽象类
  36. public class RefinedAbstraction : Abstraction
  37. {
  38.     public RefinedAbstraction(IImplementor implementor) : base(implementor) { }
  39.     public override void Operation()
  40.     {
  41.         Console.WriteLine("Refined Abstraction is calling implementor's method:");
  42.         base.Operation();
  43.     }
  44. }
复制代码
在这个代码中,Abstraction是抽象类,它有一个IImplementor接口的实例,通过这个实例调用实现类的方法。RefinedAbstraction是扩充的抽象类,它继承自Abstraction。ConcreteImplementorA和ConcreteImplementorB是实现类,它们实现了IImplementor接口。
以下是一个使用这个模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         IImplementor implementorA = new ConcreteImplementorA();
  6.         Abstraction abstractionA = new RefinedAbstraction(implementorA);
  7.         abstractionA.Operation();
  8.         IImplementor implementorB = new ConcreteImplementorB();
  9.         Abstraction abstractionB = new RefinedAbstraction(implementorB);
  10.         abstractionB.Operation();
  11.         Console.ReadLine();
  12.     }
  13. }
复制代码
在这个例子中,我们创建了两个实现类的实例,然后创建了两个抽象类的实例,每个抽象类的实例都有一个实现类的实例。当我们调用抽象类的Operation方法时,它会调用实现类的OperationImp方法。
执行流程如下:

  • 创建实现类的实例。
  • 创建抽象类的实例,抽象类的实例有一个实现类的实例。
  • 调用抽象类的Operation方法,该方法会调用实现类的OperationImp方法。
2. 组合模式(Composite)

组合模式(Composite pattern)是一种结构型设计模式,它可以使你将对象组合成树形结构,并且能像使用独立对象一样使用它们。这种模式的主要目的是使单个对象和组合对象具有一致性。
以下是在C#中实现组合模式的一个简单示例:
  1. // 抽象组件类
  2. public abstract class Component
  3. {
  4.     protected string name;
  5.     public Component(string name)
  6.     {
  7.         this.name = name;
  8.     }
  9.     public abstract void Add(Component c);
  10.     public abstract void Remove(Component c);
  11.     public abstract void Display(int depth);
  12. }
  13. // 叶节点类
  14. public class Leaf : Component
  15. {
  16.     public Leaf(string name) : base(name) { }
  17.     public override void Add(Component c)
  18.     {
  19.         Console.WriteLine("Cannot add to a leaf");
  20.     }
  21.     public override void Remove(Component c)
  22.     {
  23.         Console.WriteLine("Cannot remove from a leaf");
  24.     }
  25.     public override void Display(int depth)
  26.     {
  27.         Console.WriteLine(new String('-', depth) + name);
  28.     }
  29. }
  30. // 构件容器类
  31. public class Composite : Component
  32. {
  33.     private List<Component> _children = new List<Component>();
  34.     public Composite(string name) : base(name) { }
  35.     public override void Add(Component component)
  36.     {
  37.         _children.Add(component);
  38.     }
  39.     public override void Remove(Component component)
  40.     {
  41.         _children.Remove(component);
  42.     }
  43.     public override void Display(int depth)
  44.     {
  45.         Console.WriteLine(new String('-', depth) + name);
  46.         // 显示每个节点的子节点
  47.         foreach (Component component in _children)
  48.         {
  49.             component.Display(depth + 2);
  50.         }
  51.     }
  52. }
复制代码
在这个代码中,Component是组件抽象类,它有一个名字,并定义了添加、删除和显示操作。Leaf是叶子节点,它实现了Component的操作。Composite是组件容器,它可以添加、删除和显示其子节点。
以下是一个使用这个模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         Composite root = new Composite("root");
  6.         root.Add(new Leaf("Leaf A"));
  7.         root.Add(new Leaf("Leaf B"));
  8.         Composite comp = new Composite("Composite X");
  9.         comp.Add(new Leaf("Leaf XA"));
  10.         comp.Add(new Leaf("Leaf XB"));
  11.         root.Add(comp);
  12.         Composite comp2 = new Composite("Composite XY");
  13.         comp2.Add(new Leaf("Leaf XYA"));
  14.         comp2.Add(new Leaf("Leaf XYB"));
  15.         comp.Add(comp2);
  16.         root.Add(new Leaf("Leaf C"));
  17.         // 在组合中添加和删除
  18.         Leaf leaf = new Leaf("Leaf D");
  19.         root.Add(leaf);
  20.         root.Remove(leaf);
  21.         // 显示树形结构
  22.         root.Display(1);
  23.         Console.ReadLine();
  24.     }
  25. }
复制代码
在这个例子中,我们创建了一个根节点,并在其中添加了两个叶子节点。然后我们创建了一个复合节点,并在其中添加了两个叶子节点,然后我们把复合节点添加到根节点中。我们还在复合节点中添加了另一个复合节点。最后,我们又在根节点中添加和删除了一个叶子节点,然后显示了树的结构。
执行流程如下:

  • 创建组合和叶子对象。
  • 通过调用组合对象的Add方法将叶子对象和其他组合对象添加到组合对象中。
  • 通过调用组合对象的Remove方法将叶子对象从组合对象中移除。
  • 调用组合对象的Display方法显示组合对象的结构。
3. 装饰模式(Decorator)

装饰模式是一种结构型设计模式,它允许在运行时动态地将功能添加到对象中,这种模式提供了比继承更有弹性的解决方案。
以下是在C#中实现装饰模式的一个简单示例:
  1. // 抽象组件
  2. public abstract class Component
  3. {
  4.     public abstract string Operation();
  5. }
  6. // 具体组件
  7. public class ConcreteComponent : Component
  8. {
  9.     public override string Operation()
  10.     {
  11.         return "ConcreteComponent";
  12.     }
  13. }
  14. // 抽象装饰器
  15. public abstract class Decorator : Component
  16. {
  17.     protected Component component;
  18.     public Decorator(Component component)
  19.     {
  20.         this.component = component;
  21.     }
  22.     public override string Operation()
  23.     {
  24.         if (component != null)
  25.         {
  26.             return component.Operation();
  27.         }
  28.         else
  29.         {
  30.             return string.Empty;
  31.         }
  32.     }
  33. }
  34. // 具体装饰器A
  35. public class ConcreteDecoratorA : Decorator
  36. {
  37.     public ConcreteDecoratorA(Component comp) : base(comp) { }
  38.     public override string Operation()
  39.     {
  40.         return $"ConcreteDecoratorA({base.Operation()})";
  41.     }
  42. }
  43. // 具体装饰器B
  44. public class ConcreteDecoratorB : Decorator
  45. {
  46.     public ConcreteDecoratorB(Component comp) : base(comp) { }
  47.     public override string Operation()
  48.     {
  49.         return $"ConcreteDecoratorB({base.Operation()})";
  50.     }
  51. }
复制代码
在这个代码中,Component是一个抽象组件,它定义了一个Operation方法。ConcreteComponent是具体组件,它实现了Component的Operation方法。Decorator是一个抽象装饰器,它包含一个Component对象,并重写了Operation方法。ConcreteDecoratorA和ConcreteDecoratorB是具体的装饰器,它们继承了Decorator并重写了Operation方法,以添加新的功能。
以下是一个使用这个模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         // 基本组件
  6.         Component component = new ConcreteComponent();
  7.         Console.WriteLine("Basic Component: " + component.Operation());
  8.         // 装饰后的组件
  9.         Component decoratorA = new ConcreteDecoratorA(component);
  10.         Console.WriteLine("A Decorated: " + decoratorA.Operation());
  11.         Component decoratorB = new ConcreteDecoratorB(decoratorA);
  12.         Console.WriteLine("B Decorated: " + decoratorB.Operation());
  13.         Console.ReadLine();
  14.     }
  15. }
复制代码
在这个例子中,我们首先创建了一个ConcreteComponent对象,并调用它的Operation方法。然后我们创建了一个ConcreteDecoratorA对象,它装饰了ConcreteComponent,并调用它的Operation方法。最后,我们创建了一个ConcreteDecoratorB对象,它装饰了ConcreteDecoratorA,并调用它的Operation方法。这样,我们就可以在运行时动态地添加功能。
执行流程如下:

  • 创建一个具体组件对象并调用其操作。
  • 创建一个装饰器对象,该对象装饰了具体组件,并调用其操作。在操作中,装饰器首先调用具体组件的操作,然后执行额外的操作。
  • 创建另一个装饰器对象,装饰前一个装饰器,并调用其操作。在操作中,这个装饰器首先调用前一个装饰器的操作,然后执行额外的操作。
4. 外观模式(Facade)

外观模式是一种结构型设计模式,提供了一个统一的接口,用来访问子系统中的一群接口。外观模式定义了一个高层接口,让子系统更容易使用。
以下是在C#中实现外观模式的一个简单示例:
  1. // 子系统A
  2. public class SubSystemA
  3. {
  4.     public string OperationA()
  5.     {
  6.         return "SubSystemA, OperationA\n";
  7.     }
  8. }
  9. // 子系统B
  10. public class SubSystemB
  11. {
  12.     public string OperationB()
  13.     {
  14.         return "SubSystemB, OperationB\n";
  15.     }
  16. }
  17. // 子系统C
  18. public class SubSystemC
  19. {
  20.     public string OperationC()
  21.     {
  22.         return "SubSystemC, OperationC\n";
  23.     }
  24. }
  25. // 外观类
  26. public class Facade
  27. {
  28.     private SubSystemA a = new SubSystemA();
  29.     private SubSystemB b = new SubSystemB();
  30.     private SubSystemC c = new SubSystemC();
  31.     public string OperationWrapper()
  32.     {
  33.         string result = "Facade initializes subsystems:\n";
  34.         result += a.OperationA();
  35.         result += b.OperationB();
  36.         result += c.OperationC();
  37.         return result;
  38.     }
  39. }
复制代码
在这个代码中,SubSystemA,SubSystemB和SubSystemC都是子系统,每个子系统都有一个操作。Facade是一个外观类,它封装了对子系统的操作,提供了一个统一的接口。
以下是一个使用这个模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         Facade facade = new Facade();
  6.         Console.WriteLine(facade.OperationWrapper());
  7.         Console.ReadLine();
  8.     }
  9. }
复制代码
在这个例子中,我们创建了一个Facade对象,并调用了它的OperationWrapper方法。这个方法封装了对子系统的操作,使得客户端可以不直接操作子系统,而是通过外观类操作子系统。
执行流程如下:

  • 创建一个外观对象。
  • 通过调用外观对象的方法,间接地操作子系统。
  • 子系统的操作被封装在外观对象的方法中,客户端不需要直接操作子系统。
5. 享元模式(Flyweight)

享元模式(Flyweight Pattern)是一种结构型设计模式,该模式主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了一种减少对象数量从而改善应用所需的对象结构的方式。
以下是在C#中实现享元模式的一个简单示例:
  1. // 享元类
  2. public class Flyweight
  3. {
  4.     private string intrinsicState;
  5.     // 构造函数
  6.     public Flyweight(string intrinsicState)
  7.     {
  8.         this.intrinsicState = intrinsicState;
  9.     }
  10.     // 业务方法
  11.     public void Operation(string extrinsicState)
  12.     {
  13.         Console.WriteLine($"Intrinsic State = {intrinsicState}, Extrinsic State = {extrinsicState}");
  14.     }
  15. }
  16. // 享元工厂类
  17. public class FlyweightFactory
  18. {
  19.     private Dictionary<string, Flyweight> flyweights = new Dictionary<string, Flyweight>();
  20.     public Flyweight GetFlyweight(string key)
  21.     {
  22.         if (!flyweights.ContainsKey(key))
  23.         {
  24.             flyweights[key] = new Flyweight(key);
  25.         }
  26.         return flyweights[key];
  27.     }
  28.     public int GetFlyweightCount()
  29.     {
  30.         return flyweights.Count;
  31.     }
  32. }
复制代码
在这个代码中,Flyweight是享元类,它有一个内在状态intrinsicState,这个状态是不变的。FlyweightFactory是享元工厂类,它维护了一个享元对象的集合。
以下是一个使用这个模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         FlyweightFactory factory = new FlyweightFactory();
  6.         Flyweight flyweightA = factory.GetFlyweight("A");
  7.         flyweightA.Operation("A operation");
  8.         Flyweight flyweightB = factory.GetFlyweight("B");
  9.         flyweightB.Operation("B operation");
  10.         Flyweight flyweightC = factory.GetFlyweight("A");
  11.         flyweightC.Operation("C operation");
  12.         Console.WriteLine($"Total Flyweights: {factory.GetFlyweightCount()}");
  13.         Console.ReadLine();
  14.     }
  15. }
复制代码
在这个例子中,我们创建了一个FlyweightFactory对象,并通过它创建了两个享元对象。注意,当我们试图创建第三个享元对象时,工厂实际上返回了第一个享元对象的引用,因为这两个对象的内在状态是相同的。
执行流程如下:

  • 创建一个享元工厂对象。
  • 通过享元工厂获取享元对象。如果对象已经存在,则返回现有对象;否则,创建新对象。
  • 执行享元对象的操作。
  • 显示当前享元对象的数量。
6. 代理模式(Proxy)

代理模式是一种结构型设计模式,它提供了一个对象代替另一个对象来控制对它的访问。代理对象可以在客户端和目标对象之间起到中介的作用,并添加其他的功能。
以下是在C#中实现代理模式的一个简单示例:
  1. // 抽象主题接口
  2. public interface ISubject
  3. {
  4.     void Request();
  5. }
  6. // 真实主题
  7. public class RealSubject : ISubject
  8. {
  9.     public void Request()
  10.     {
  11.         Console.WriteLine("RealSubject: Handling Request.");
  12.     }
  13. }
  14. // 代理
  15. public class Proxy : ISubject
  16. {
  17.     private RealSubject _realSubject;
  18.     public Proxy(RealSubject realSubject)
  19.     {
  20.         this._realSubject = realSubject;
  21.     }
  22.     public void Request()
  23.     {
  24.         if (this.CheckAccess())
  25.         {
  26.             this._realSubject.Request();
  27.             this.LogAccess();
  28.         }
  29.     }
  30.     public bool CheckAccess()
  31.     {
  32.         // 检查是否有权限访问
  33.         Console.WriteLine("Proxy: Checking access prior to firing a real request.");
  34.         return true;
  35.     }
  36.     public void LogAccess()
  37.     {
  38.         // 记录请求
  39.         Console.WriteLine("Proxy: Logging the time of request.");
  40.     }
  41. }
复制代码
在这个代码中,ISubject是一个接口,定义了Request方法。RealSubject是实现了ISubject接口的类,Proxy是代理类,它也实现了ISubject接口,并持有一个RealSubject对象的引用。
以下是一个使用这个模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         Console.WriteLine("Client: Executing the client code with a real subject:");
  6.         RealSubject realSubject = new RealSubject();
  7.         realSubject.Request();
  8.         Console.WriteLine();
  9.         Console.WriteLine("Client: Executing the same client code with a proxy:");
  10.         Proxy proxy = new Proxy(realSubject);
  11.         proxy.Request();
  12.         Console.ReadLine();
  13.     }
  14. }
复制代码
在这个例子中,我们首先直接调用了RealSubject的Request方法,然后我们通过代理调用了相同的方法。注意,在通过代理调用Request方法时,代理还执行了其他的操作,如检查访问权限和记录日志。
执行流程如下:

  • 创建一个真实主题对象,并直接调用其Request方法。
  • 创建一个代理对象,代理对象包含一个真实主题的引用。
  • 通过代理对象调用Request方法。在这个方法中,代理首先检查访问权限,然后调用真实主题的Request方法,最后记录日志。
行为型模式: 13. 责任链模式(Chain of Responsibility)

1. 命令模式(Command)

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。在命令模式中,请求在对象中封装成为一个操作或行为,这些请求被送到调用对象,调用对象寻找可以处理该命令的合适的对象,并把命令直接送达到对应的对象,该对象会执行这些命令。
以下是在C#中实现命令模式的一个简单示例:
  1. // 命令接口
  2. public interface ICommand
  3. {
  4.     void Execute();
  5. }
  6. // 具体命令类
  7. public class ConcreteCommand : ICommand
  8. {
  9.     private Receiver receiver;
  10.     public ConcreteCommand(Receiver receiver)
  11.     {
  12.         this.receiver = receiver;
  13.     }
  14.     public void Execute()
  15.     {
  16.         receiver.Action();
  17.     }
  18. }
  19. // 接收者类
  20. public class Receiver
  21. {
  22.     public void Action()
  23.     {
  24.         Console.WriteLine("Receiver performs an action");
  25.     }
  26. }
  27. // 调用者或发送者类
  28. public class Invoker
  29. {
  30.     private ICommand command;
  31.     public void SetCommand(ICommand command)
  32.     {
  33.         this.command = command;
  34.     }
  35.     public void ExecuteCommand()
  36.     {
  37.         command.Execute();
  38.     }
  39. }
复制代码
在这个代码中,ICommand是命令接口,定义了Execute方法。ConcreteCommand是具体的命令类,它实现了ICommand接口,并持有一个Receiver对象的引用。Invoker是调用者或发送者类,它持有一个ICommand对象的引用,并可以通过SetCommand方法设置命令,通过ExecuteCommand方法执行命令。
以下是一个使用这个模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         Receiver receiver = new Receiver();
  6.         ICommand command = new ConcreteCommand(receiver);
  7.         Invoker invoker = new Invoker();
  8.         invoker.SetCommand(command);
  9.         invoker.ExecuteCommand();
  10.         Console.ReadLine();
  11.     }
  12. }
复制代码
在这个例子中,我们创建了一个Receiver对象、一个ConcreteCommand对象和一个Invoker对象。然后我们通过Invoker的SetCommand方法设置了命令,并通过ExecuteCommand方法执行了命令。
执行流程如下:

  • 创建一个接收者对象。
  • 创建一个具体命令对象,并将接收者对象传递给它。
  • 创建一个调用者或发送者对象。
  • 通过调用者对象的SetCommand方法设置命令。
  • 通过调用者对象的ExecuteCommand方法执行命令。
2. 解释器模式(Interpreter)

解释器模式(Interpreter Pattern)是一种行为型设计模式,用于解决一些固定语法格式的需求。它定义了如何在语言中表示和解析语法。
以下是在C#中实现解释器模式的一个简单示例:
  1. // 抽象表达式
  2. public interface IExpression
  3. {
  4.     bool Interpret(string context);
  5. }
  6. // 终结符表达式
  7. public class TerminalExpression : IExpression
  8. {
  9.     private string data;
  10.     public TerminalExpression(string data)
  11.     {
  12.         this.data = data;
  13.     }
  14.     public bool Interpret(string context)
  15.     {
  16.         if (context.Contains(data))
  17.         {
  18.             return true;
  19.         }
  20.         return false;
  21.     }
  22. }
  23. // 非终结符表达式
  24. public class OrExpression : IExpression
  25. {
  26.     private IExpression expr1 = null;
  27.     private IExpression expr2 = null;
  28.     public OrExpression(IExpression expr1, IExpression expr2)
  29.     {
  30.         this.expr1 = expr1;
  31.         this.expr2 = expr2;
  32.     }
  33.     public bool Interpret(string context)
  34.     {
  35.         return expr1.Interpret(context) || expr2.Interpret(context);
  36.     }
  37. }
复制代码
在这个代码中,IExpression是抽象表达式,定义了Interpret方法。TerminalExpression是终结符表达式,它实现了IExpression接口。OrExpression是非终结符表达式,它也实现了IExpression接口。
以下是一个使用这个模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         IExpression isMale = GetMaleExpression();
  6.         IExpression isMarriedWoman = GetMarriedWomanExpression();
  7.         Console.WriteLine($"John is male? {isMale.Interpret("John")}");
  8.         Console.WriteLine($"Julie is a married women? {isMarriedWoman.Interpret("Married Julie")}");
  9.         Console.ReadLine();
  10.     }
  11.     // 规则:Robert 和 John 是男性
  12.     public static IExpression GetMaleExpression()
  13.     {
  14.         IExpression robert = new TerminalExpression("Robert");
  15.         IExpression john = new TerminalExpression("John");
  16.         return new OrExpression(robert, john);
  17.     }
  18.     // 规则:Julie 是一个已婚的女性
  19.     public static IExpression GetMarriedWomanExpression()
  20.     {
  21.         IExpression julie = new TerminalExpression("Julie");
  22.         IExpression married = new TerminalExpression("Married");
  23.         return new OrExpression(julie, married);
  24.     }
  25. }
复制代码
在这个例子中,我们定义了两个规则,"Robert和John是男性"和"Julie是一个已婚的女性"。我们然后创建了两个表达式对象,分别表示这两个规则,并使用这两个对象来解析输入。
执行流程如下:

  • 创建终结符表达式对象和非终结符表达式对象,用于表示规则。
  • 调用表达式对象的Interpret方法,解析输入的字符串。
  • 输出解析结果。
3. 迭代器模式(Iterator)

迭代器模式(Iterator Pattern)是一种行为型设计模式,它提供了一种方法来访问一个对象的元素,而不需要暴露该对象的内部表示。以下是在C#中实现迭代器模式的一个简单示例:
  1. // 抽象聚合类
  2. public interface IAggregate
  3. {
  4.     IIterator CreateIterator();
  5.     void Add(string item);
  6.     int Count { get; }
  7.     string this[int index] { get; set; }
  8. }
  9. // 具体聚合类
  10. public class ConcreteAggregate : IAggregate
  11. {
  12.     private List<string> items = new List<string>();
  13.     public IIterator CreateIterator()
  14.     {
  15.         return new ConcreteIterator(this);
  16.     }
  17.     public int Count
  18.     {
  19.         get { return items.Count; }
  20.     }
  21.     public string this[int index]
  22.     {
  23.         get { return items[index]; }
  24.         set { items.Insert(index, value); }
  25.     }
  26.     public void Add(string item)
  27.     {
  28.         items.Add(item);
  29.     }
  30. }
  31. // 抽象迭代器
  32. public interface IIterator
  33. {
  34.     string First();
  35.     string Next();
  36.     bool IsDone { get; }
  37.     string CurrentItem { get; }
  38. }
  39. // 具体迭代器
  40. public class ConcreteIterator : IIterator
  41. {
  42.     private ConcreteAggregate aggregate;
  43.     private int current = 0;
  44.     public ConcreteIterator(ConcreteAggregate aggregate)
  45.     {
  46.         this.aggregate = aggregate;
  47.     }
  48.     public string First()
  49.     {
  50.         return aggregate[0];
  51.     }
  52.     public string Next()
  53.     {
  54.         string ret = null;
  55.         if (current < aggregate.Count - 1)
  56.         {
  57.             ret = aggregate[++current];
  58.         }
  59.         return ret;
  60.     }
  61.     public string CurrentItem
  62.     {
  63.         get { return aggregate[current]; }
  64.     }
  65.     public bool IsDone
  66.     {
  67.         get { return current >= aggregate.Count; }
  68.     }
  69. }
复制代码
在这个代码中,IAggregate是抽象聚合类,定义了CreateIterator等方法,ConcreteAggregate是具体聚合类,实现了IAggregate接口。IIterator是抽象迭代器,定义了First、Next等方法,ConcreteIterator是具体迭代器,实现了IIterator接口。
以下是一个使用这个模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         IAggregate aggregate = new ConcreteAggregate();
  6.         aggregate.Add("Item A");
  7.         aggregate.Add("Item B");
  8.         aggregate.Add("Item C");
  9.         aggregate.Add("Item D");
  10.         IIterator iterator = aggregate.CreateIterator();
  11.         Console.WriteLine("Iterating over collection:");
  12.         string item = iterator.First();
  13.         while (item != null)
  14.         {
  15.             Console.WriteLine(item);
  16.             item = iterator.Next();
  17.         }
  18.         Console.ReadLine();
  19.     }
  20. }
复制代码
在这个例子中,我们创建了一个ConcreteAggregate对象,并添加了几个元素。然后我们通过CreateIterator方法创建了一个迭代器,并使用这个迭代器遍历了集合中的所有元素。
执行流程如下:

  • 创建一个聚合对象,并添加一些元素。
  • 通过聚合对象的CreateIterator方法创建一个迭代器。
  • 通过迭代器的First方法获取第一个元素,然后通过Next方法获取后续的元素,直到获取不到元素为止。
4. 中介者模式(Mediator)

中介者模式是一种行为设计模式,它让你能减少一组对象之间复杂的通信。它提供了一个中介者对象,此对象负责在组中的对象之间进行通信,而不是这些对象直接进行通信。
首先,让我们定义一个中介者接口和一个具体的中介者:
  1. // Mediator 接口声明了与组件交互的方法。
  2. public interface IMediator
  3. {
  4.     void Notify(object sender, string ev);
  5. }
  6. // 具体 Mediators 实现协作行为,它负责协调多个组件。
  7. public class ConcreteMediator : IMediator
  8. {
  9.     private Component1 _component1;
  10.     private Component2 _component2;
  11.     public ConcreteMediator(Component1 component1, Component2 component2)
  12.     {
  13.         _component1 = component1;
  14.         _component1.SetMediator(this);
  15.         _component2 = component2;
  16.         _component2.SetMediator(this);
  17.     }
  18.     public void Notify(object sender, string ev)
  19.     {
  20.         if (ev == "A")
  21.         {
  22.             Console.WriteLine("Mediator reacts on A and triggers following operations:");
  23.             this._component2.DoC();
  24.         }
  25.         if (ev == "D")
  26.         {
  27.             Console.WriteLine("Mediator reacts on D and triggers following operations:");
  28.             this._component1.DoB();
  29.             this._component2.DoC();
  30.         }
  31.     }
  32. }
复制代码
接着,我们定义一个基础组件类和两个具体组件:
  1. public abstract class BaseComponent
  2. {
  3.     protected IMediator _mediator;
  4.     public BaseComponent(IMediator mediator = null)
  5.     {
  6.         _mediator = mediator;
  7.     }
  8.     public void SetMediator(IMediator mediator)
  9.     {
  10.         this._mediator = mediator;
  11.     }
  12. }
  13. // 具体 Components 实现各种功能。它们不依赖于其他组件。
  14. // 它们也不依赖于任何具体 Mediator 类。
  15. public class Component1 : BaseComponent
  16. {
  17.     public void DoA()
  18.     {
  19.         Console.WriteLine("Component 1 does A.");
  20.         this._mediator.Notify(this, "A");
  21.     }
  22.     public void DoB()
  23.     {
  24.         Console.WriteLine("Component 1 does B.");
  25.         this._mediator.Notify(this, "B");
  26.     }
  27. }
  28. public class Component2 : BaseComponent
  29. {
  30.     public void DoC()
  31.     {
  32.         Console.WriteLine("Component 2 does C.");
  33.         this._mediator.Notify(this, "C");
  34.     }
  35.     public void DoD()
  36.     {
  37.         Console.WriteLine("Component 2 does D.");
  38.         this._mediator.Notify(this, "D");
  39.     }
  40. }
复制代码
最后,我们来创建一个客户端代码:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         // The client code.
  6.         Component1 component1 = new Component1();
  7.         Component2 component2 = new Component2();
  8.         new ConcreteMediator(component1, component2);
  9.         Console.WriteLine("Client triggers operation A.");
  10.         component1.DoA();
  11.         Console.WriteLine();
  12.         Console.WriteLine("Client triggers operation D.");
  13.         component2.DoD();
  14.     }
  15. }
复制代码
这个示例中的各个组件通过中介者来进行通信,而不是直接通信,这样就可以减少组件之间的依赖性,使得它们可以更容易地被独立修改。当一个组件发生某个事件(例如"Component 1 does A")时,它会通过中介者来通知其他组件,这样其他组件就可以根据这个事件来做出响应(例如"Component 2 does C")。
5. 备忘录模式(Memento)

备忘录模式是一种行为设计模式,它能保存对象的状态,以便在后面可以恢复它。在大多数情况下,这种模式可以让你在不破坏对象封装的前提下,保存和恢复对象的历史状态。
以下是一个简单的备忘录模式的实现,其中有三个主要的类:Originator(保存了一个重要的状态,这个状态可能会随着时间改变),Memento(保存了Originator的一个快照,这个快照包含了Originator的状态),以及Caretaker(负责保存Memento)。
  1. // Originator 类可以生成一个备忘录,并且可以通过备忘录恢复其状态。
  2. public class Originator
  3. {
  4.     private string _state;
  5.     public Originator(string state)
  6.     {
  7.         this._state = state;
  8.         Console.WriteLine($"Originator: My initial state is: {_state}");
  9.     }
  10.     public void DoSomething()
  11.     {
  12.         Console.WriteLine("Originator: I'm doing something important.");
  13.         _state = GenerateRandomString(30);
  14.         Console.WriteLine($"Originator: and my state has changed to: {_state}");
  15.     }
  16.     private string GenerateRandomString(int length = 10)
  17.     {
  18.         string allowedSymbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  19.         string result = string.Empty;
  20.         while (length > 0)
  21.         {
  22.             result += allowedSymbols[new Random().Next(0, allowedSymbols.Length)];
  23.             length--;
  24.         }
  25.         return result;
  26.     }
  27.     public IMemento Save()
  28.     {
  29.         return new ConcreteMemento(_state);
  30.     }
  31.     public void Restore(IMemento memento)
  32.     {
  33.         _state = memento.GetState();
  34.         Console.WriteLine($"Originator: My state has changed to: {_state}");
  35.     }
  36. }
  37. // 备忘录接口提供了获取备忘录和原发器状态的方法。但在该接口中并未声明所有的方法,一些方法只在原发器中声明。
  38. public interface IMemento
  39. {
  40.     string GetName();
  41.     string GetState();
  42.     DateTime GetDate();
  43. }
  44. // Concrete Memento 存储原发器状态,并通过原发器实现备份。备忘录是不可变的,因此,没有 set 方法。
  45. public class ConcreteMemento : IMemento
  46. {
  47.     private string _state;
  48.     private DateTime _date;
  49.     public ConcreteMemento(string state)
  50.     {
  51.         _state = state;
  52.         _date = DateTime.Now;
  53.     }
  54.     public string GetState()
  55.     {
  56.         return _state;
  57.     }
  58.     public string GetName()
  59.     {
  60.         return $"{_date} / ({_state.Substring(0, 9)})...";
  61.     }
  62.     public DateTime GetDate()
  63.     {
  64.         return _date;
  65.     }
  66. }
  67. // Caretaker 不依赖于具体备忘录类。结果,它不会有任何访问原发器状态的权利,它只能获取备忘录的元数据。
  68. public class Caretaker
  69. {
  70.     private List<IMemento> _mementos = new List<IMemento>();
  71.     private Originator _originator = null;
  72.     public Caretaker(Originator originator)
  73.     {
  74.         this._originator = originator;
  75.     }
  76.     public void Backup()
  77.     {
  78.         Console.WriteLine("\nCaretaker: Saving Originator's state...");
  79.         _mementos.Add(_originator.Save());
  80.     }
  81.     public void Undo()
  82.     {
  83.         if (_mementos.Count == 0)
  84.         {
  85.             return;
  86.         }
  87.         var memento = _mementos.Last();
  88.         _mementos.Remove(memento);
  89.         Console.WriteLine("Caretaker: Restoring state to: " + memento.GetName());
  90.         try
  91.         {
  92.             _originator.Restore(memento);
  93.         }
  94.         catch (Exception)
  95.         {
  96.             Undo();
  97.         }
  98.     }
  99.     public void ShowHistory()
  100.     {
  101.         Console.WriteLine("Caretaker: Here's the list of mementos:");
  102.         foreach (var memento in _mementos)
  103.         {
  104.             Console.WriteLine(memento.GetName());
  105.         }
  106.     }
  107. }
  108. // 客户端代码
  109. class Program
  110. {
  111.     static void Main(string[] args)
  112.     {
  113.         Originator originator = new Originator("Super-duper-super-puper-super.");
  114.         Caretaker caretaker = new Caretaker(originator);
  115.         caretaker.Backup();
  116.         originator.DoSomething();
  117.         caretaker.Backup();
  118.         originator.DoSomething();
  119.         caretaker.Backup();
  120.         originator.DoSomething();
  121.         Console.WriteLine();
  122.         caretaker.ShowHistory();
  123.         Console.WriteLine("\nClient: Now, let's rollback!\n");
  124.         caretaker.Undo();
  125.         Console.WriteLine("\nClient: Once more!\n");
  126.         caretaker.Undo();
  127.     }
  128. }
复制代码
以上的代码中,Originator 持有一些重要的状态,并且提供了方法去保存它的状态到一个备忘录对象以及从备忘录对象中恢复它的状态。Caretaker 负责保存备忘录,但是它不能操作备忘录对象中的状态。当用户执行操作时,我们先保存当前的状态,然后执行操作。如果用户后来不满意新的状态,他们可以方便地从旧的备忘录中恢复状态。
6. 观察者模式(Observer)

观察者模式(Observer Pattern)是一种行为型设计模式,当一个对象的状态发生变化时,依赖它的所有对象都会得到通知并被自动更新。以下是在C#中实现观察者模式的一个简单示例:
  1. // 抽象观察者
  2. public interface IObserver
  3. {
  4.     void Update();
  5. }
  6. // 具体观察者
  7. public class ConcreteObserver : IObserver
  8. {
  9.     private string name;
  10.     public ConcreteObserver(string name)
  11.     {
  12.         this.name = name;
  13.     }
  14.     public void Update()
  15.     {
  16.         Console.WriteLine($"{name} received an update!");
  17.     }
  18. }
  19. // 抽象主题
  20. public interface ISubject
  21. {
  22.     void RegisterObserver(IObserver observer);
  23.     void RemoveObserver(IObserver observer);
  24.     void NotifyObservers();
  25. }
  26. // 具体主题
  27. public class ConcreteSubject : ISubject
  28. {
  29.     private List<IObserver> observers = new List<IObserver>();
  30.     public void RegisterObserver(IObserver observer)
  31.     {
  32.         observers.Add(observer);
  33.     }
  34.     public void RemoveObserver(IObserver observer)
  35.     {
  36.         if (observers.Contains(observer))
  37.         {
  38.             observers.Remove(observer);
  39.         }
  40.     }
  41.     public void NotifyObservers()
  42.     {
  43.         foreach (var observer in observers)
  44.         {
  45.             observer.Update();
  46.         }
  47.     }
  48.     public void ChangeState()
  49.     {
  50.         // 触发状态变化,通知所有观察者
  51.         NotifyObservers();
  52.     }
  53. }
复制代码
在这个代码中,IObserver是抽象观察者,定义了Update方法,ConcreteObserver是具体观察者,实现了IObserver接口。ISubject是抽象主题,定义了RegisterObserver、RemoveObserver和NotifyObservers方法,ConcreteSubject是具体主题,实现了ISubject接口。
以下是一个使用这个模式的示例:
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         ConcreteSubject subject = new ConcreteSubject();
  6.         subject.RegisterObserver(new ConcreteObserver("Observer 1"));
  7.         subject.RegisterObserver(new ConcreteObserver("Observer 2"));
  8.         subject.RegisterObserver(new ConcreteObserver("Observer 3"));
  9.         subject.ChangeState();
  10.         Console.ReadLine();
  11.     }
  12. }
复制代码
在这个例子中,我们创建了一个ConcreteSubject对象,并注册了三个观察者。然后我们通过ChangeState方法改变了主题的状态,这会触发主题通知所有观察者。
执行流程如下:

  • 创建一个具体主题对象。
  • 创建几个具体观察者对象,并通过主题的RegisterObserver方法将这些观察者注册到主题中。
  • 通过主题的ChangeState方法改变主题的状态,这会触发主题通知所有观察者。
7. 状态模式(State)

状态模式在面向对象编程中,是一种允许对象在其内部状态改变时改变其行为的设计模式。这种类型的设计模式属于行为型模式。在状态模式中,我们创建对象表示各种状态,以及一个行为随状态改变而改变的上下文对象。
以下是一个状态模式的示例。这个示例中,我们将创建一个银行账户,它有两个状态:正常状态(NormalState)和透支状态(OverdrawnState)。当用户执行操作(存款和取款)时,账户状态将相应地进行更改。
首先,我们定义一个表示状态的接口:
  1. public interface IAccountState
  2. {
  3.     void Deposit(Action addToBalance);
  4.     void Withdraw(Action subtractFromBalance);
  5.     void ComputeInterest();
  6. }
复制代码
然后,我们创建两个表示具体状态的类:
  1. public class NormalState : IAccountState
  2. {
  3.     public void Deposit(Action addToBalance)
  4.     {
  5.         addToBalance();
  6.         Console.WriteLine("Deposit in NormalState");
  7.     }
  8.     public void Withdraw(Action subtractFromBalance)
  9.     {
  10.         subtractFromBalance();
  11.         Console.WriteLine("Withdraw in NormalState");
  12.     }
  13.     public void ComputeInterest()
  14.     {
  15.         Console.WriteLine("Interest computed in NormalState");
  16.     }
  17. }
  18. public class OverdrawnState : IAccountState
  19. {
  20.     public void Deposit(Action addToBalance)
  21.     {
  22.         addToBalance();
  23.         Console.WriteLine("Deposit in OverdrawnState");
  24.     }
  25.     public void Withdraw(Action subtractFromBalance)
  26.     {
  27.         Console.WriteLine("No withdraw in OverdrawnState");
  28.     }
  29.     public void ComputeInterest()
  30.     {
  31.         Console.WriteLine("Interest and fees computed in OverdrawnState");
  32.     }
  33. }
复制代码
然后,我们创建一个Context类,它使用这些状态来执行其任务:
  1. public class BankAccount
  2. {
  3.     private IAccountState _state;
  4.     private double _balance;
  5.     public BankAccount(IAccountState state)
  6.     {
  7.         _state = state;
  8.         _balance = 0;
  9.     }
  10.     public void Deposit(double amount)
  11.     {
  12.         _state.Deposit(() => _balance += amount);
  13.         StateChangeCheck();
  14.     }
  15.     public void Withdraw(double amount)
  16.     {
  17.         _state.Withdraw(() => _balance -= amount);
  18.         StateChangeCheck();
  19.     }
  20.     public void ComputeInterest()
  21.     {
  22.         _state.ComputeInterest();
  23.     }
  24.     private void StateChangeCheck()
  25.     {
  26.         if (_balance < 0.0)
  27.             _state = new OverdrawnState();
  28.         else
  29.             _state = new NormalState();
  30.     }
  31. }
复制代码
现在,你可以创建一个实例并运行一个Demo来测试这个状态模式的代码:
  1. public class Program
  2. {
  3.     public static void Main(string[] args)
  4.     {
  5.         var account = new BankAccount(new NormalState());
  6.         account.Deposit(1000); // Deposit in NormalState
  7.         account.Withdraw(2000); // Withdraw in NormalState; No withdraw in OverdrawnState
  8.         account.Deposit(100); // Deposit in OverdrawnState
  9.         account.ComputeInterest(); // Interest and fees computed in OverdrawnState
  10.         Console.ReadKey();
  11.     }
  12. }
复制代码
这个程序首先在正常状态下进行存款操作,然后尝试进行取款操作。由于取款金额超过账户余额,所以账户进入透支状态,并阻止进一步的取款操作。但存款仍然被允许,以使账户回归到正常状态。计算利息的行为也根据账户的状态变化而变化。
8. 策略模式(Strategy)

策略模式定义了一系列的算法,并将每一个算法封装起来,使得它们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
以下是一个简单的策略模式的C#实现。这个例子中,我们将创建一个排序策略,比如快速排序和冒泡排序,它们实现同一个接口,然后创建一个Context类,它使用这些策略来执行排序操作。
首先,我们定义一个表示排序策略的接口:
  1. public interface ISortStrategy
  2. {
  3.     void Sort(List<int> list);
  4. }
复制代码
然后,我们创建两个表示具体策略的类:
  1. public class QuickSort : ISortStrategy
  2. {
  3.     public void Sort(List<int> list)
  4.     {
  5.         list.Sort();  // Quick sort is in-place but here we are using built-in method
  6.         Console.WriteLine("QuickSorted list ");
  7.     }
  8. }
  9. public class BubbleSort : ISortStrategy
  10. {
  11.     public void Sort(List<int> list)
  12.     {
  13.         int n = list.Count;
  14.         for (int i = 0; i < n - 1; i++)
  15.             for (int j = 0; j < n - i - 1; j++)
  16.                 if (list[j] > list[j + 1])
  17.                 {
  18.                     // swap temp and list[i]
  19.                     int temp = list[j];
  20.                     list[j] = list[j + 1];
  21.                     list[j + 1] = temp;
  22.                 }
  23.         Console.WriteLine("BubbleSorted list ");
  24.     }
  25. }
复制代码
然后,我们创建一个Context类,它使用这些策略来执行其任务:
  1. public class SortedList
  2. {
  3.     private List<int> _list = new List<int>();
  4.     private ISortStrategy _sortstrategy;
  5.     public void SetSortStrategy(ISortStrategy sortstrategy)
  6.     {
  7.         this._sortstrategy = sortstrategy;
  8.     }
  9.     public void Add(int num)
  10.     {
  11.         _list.Add(num);
  12.     }
  13.     public void Sort()
  14.     {
  15.         _sortstrategy.Sort(_list);
  16.         // Print sorted list
  17.         foreach (int num in _list)
  18.         {
  19.             Console.Write(num + " ");
  20.         }
  21.         Console.WriteLine();
  22.     }
  23. }
复制代码
现在,你可以创建一个实例并运行一个Demo来测试这个策略模式的代码:
  1. public class Program
  2. {
  3.     public static void Main(string[] args)
  4.     {
  5.         SortedList sortedList = new SortedList();
  6.         sortedList.Add(1);
  7.         sortedList.Add(5);
  8.         sortedList.Add(3);
  9.         sortedList.Add(4);
  10.         sortedList.Add(2);
  11.         sortedList.SetSortStrategy(new QuickSort());
  12.         sortedList.Sort();  // Output: QuickSorted list 1 2 3 4 5
  13.         sortedList.SetSortStrategy(new BubbleSort());
  14.         sortedList.Sort();  // Output: BubbleSorted list 1 2 3 4 5
  15.         Console.ReadKey();
  16.     }
  17. }
复制代码
这个程序首先创建了一个未排序的列表,然后它首先使用快速排序策略进行排序,接着又使用冒泡排序策略进行排序。
9. 模板方法模式(Template Method)

模板方法模式定义了一个操作中算法的骨架,将这些步骤延迟到子类中。模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
以下是一个模板方法模式的示例。这个示例中,我们将创建一个烹饪食物的过程,这个过程有一些固定的步骤(例如准备材料,清理),但是具体的烹饪步骤则取决于具体的食物。
首先,我们定义一个抽象的模板类:
  1. public abstract class CookingProcedure
  2. {
  3.     // The 'Template method'
  4.     public void PrepareDish()
  5.     {
  6.         PrepareIngredients();
  7.         Cook();
  8.         CleanUp();
  9.     }
  10.     public void PrepareIngredients()
  11.     {
  12.         Console.WriteLine("Preparing the ingredients...");
  13.     }
  14.     // These methods will be overridden by subclasses
  15.     public abstract void Cook();
  16.     public void CleanUp()
  17.     {
  18.         Console.WriteLine("Cleaning up...");
  19.     }
  20. }
复制代码
然后,我们创建两个具体的子类,它们分别实现了具体的烹饪步骤:
  1. public class CookPasta : CookingProcedure
  2. {
  3.     public override void Cook()
  4.     {
  5.         Console.WriteLine("Cooking pasta...");
  6.     }
  7. }
  8. public class BakeCake : CookingProcedure
  9. {
  10.     public override void Cook()
  11.     {
  12.         Console.WriteLine("Baking cake...");
  13.     }
  14. }
复制代码
现在,你可以创建一个实例并运行一个Demo来测试这个模板方法模式的代码:
  1. public class Program
  2. {
  3.     public static void Main(string[] args)
  4.     {
  5.         CookingProcedure cookingProcedure = new CookPasta();
  6.         cookingProcedure.PrepareDish();
  7.         Console.WriteLine();
  8.         cookingProcedure = new BakeCake();
  9.         cookingProcedure.PrepareDish();
  10.         Console.ReadKey();
  11.     }
  12. }
复制代码
在这个程序中,我们首先创建了一个CookPasta对象,然后调用其PrepareDish方法。然后,我们创建了一个BakeCake对象,再次调用其PrepareDish方法。这两个对象虽然具有不同的Cook方法,但是它们的PrepareDish方法的结构(即算法的骨架)是相同的。
10. 访问者模式(Visitor)

访问者模式(Visitor Pattern)是一种将算法与对象结构分离的软件设计模式。这种模式的基本想法就是通过所谓的"访问者"来改变元素的操作。这样一来,元素的类可以用于表示元素结构,而具体的操作则可以在访问者类中定义。
以下是一个使用C#实现的访问者模式示例,包括了详细的注释和执行流程。
这个示例中有三个主要部分:访问者(IVisitor)、可访问元素(IElement)和元素结构(ObjectStructure)。同时有具体访问者(ConcreteVisitor)和具体元素(ConcreteElement)。
  1. // 访问者接口
  2. public interface IVisitor
  3. {
  4.     void VisitConcreteElementA(ConcreteElementA concreteElementA);
  5.     void VisitConcreteElementB(ConcreteElementB concreteElementB);
  6. }
  7. // 具体访问者A
  8. public class ConcreteVisitorA : IVisitor
  9. {
  10.     public void VisitConcreteElementA(ConcreteElementA concreteElementA)
  11.     {
  12.         Console.WriteLine($"{concreteElementA.GetType().Name} is being visited by {this.GetType().Name}");
  13.     }
  14.     public void VisitConcreteElementB(ConcreteElementB concreteElementB)
  15.     {
  16.         Console.WriteLine($"{concreteElementB.GetType().Name} is being visited by {this.GetType().Name}");
  17.     }
  18. }
  19. // 具体访问者B
  20. public class ConcreteVisitorB : IVisitor
  21. {
  22.     public void VisitConcreteElementA(ConcreteElementA concreteElementA)
  23.     {
  24.         Console.WriteLine($"{concreteElementA.GetType().Name} is being visited by {this.GetType().Name}");
  25.     }
  26.     public void VisitConcreteElementB(ConcreteElementB concreteElementB)
  27.     {
  28.         Console.WriteLine($"{concreteElementB.GetType().Name} is being visited by {this.GetType().Name}");
  29.     }
  30. }
  31. // 元素接口
  32. public interface IElement
  33. {
  34.     void Accept(IVisitor visitor);
  35. }
  36. // 具体元素A
  37. public class ConcreteElementA : IElement
  38. {
  39.     public void Accept(IVisitor visitor)
  40.     {
  41.         visitor.VisitConcreteElementA(this);
  42.     }
  43. }
  44. // 具体元素B
  45. public class ConcreteElementB : IElement
  46. {
  47.     public void Accept(IVisitor visitor)
  48.     {
  49.         visitor.VisitConcreteElementB(this);
  50.     }
  51. }
  52. // 对象结构
  53. public class ObjectStructure
  54. {
  55.     private List<IElement> _elements = new List<IElement>();
  56.     public void Attach(IElement element)
  57.     {
  58.         _elements.Add(element);
  59.     }
  60.     public void Detach(IElement element)
  61.     {
  62.         _elements.Remove(element);
  63.     }
  64.     public void Accept(IVisitor visitor)
  65.     {
  66.         foreach (var element in _elements)
  67.         {
  68.             element.Accept(visitor);
  69.         }
  70.     }
  71. }
复制代码
执行流程如下:

  • 创建具体元素ConcreteElementA和ConcreteElementB的实例。
  • 创建对象结构ObjectStructure的实例,并将步骤1创建的具体元素添加到对象结构中。
  • 创建具体访问者ConcreteVisitorA和ConcreteVisitorB的实例。
  • 调用对象结构的Accept方法,传入步骤3创建的具体访问者,使具体访问者访问对象结构中的所有元素。
以下是一个使用上述代码的示例:
  1. public class Program
  2. {
  3.     public static void Main()
  4.     {
  5.         ObjectStructure objectStructure = new ObjectStructure();
  6.         objectStructure.Attach(new ConcreteElementA());
  7.         objectStructure.Attach(new ConcreteElementB());
  8.         ConcreteVisitorA visitorA = new ConcreteVisitorA();
  9.         ConcreteVisitorB visitorB = new ConcreteVisitorB();
  10.         objectStructure.Accept(visitorA);
  11.         objectStructure.Accept(visitorB);
  12.         Console.ReadKey();
  13.     }
  14. }
复制代码
这个程序会打印出访问者A和访问者B分别访问具体元素A和具体元素B的信息。
技术交流

.NET Core交流群:737776595
来自token的分享

来源:https://www.cnblogs.com/hejiale010426/archive/2023/06/05/17457761.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具