做图解的网站,模板网文,官网建设需求,crm系统介绍c#实现23种常见的设计模式 设计模式通常分为三个主要类别#xff1a; 创建型模式 结构型模式 行为型模式。
这些模式是用于解决常见的对象导向设计问题的最佳实践。
以下是23种常见的设计模式并且提供c#代码案例#xff1a;
创建型模式#xff1a;
1. 单例模式#…c#实现23种常见的设计模式 设计模式通常分为三个主要类别 创建型模式 结构型模式 行为型模式。
这些模式是用于解决常见的对象导向设计问题的最佳实践。
以下是23种常见的设计模式并且提供c#代码案例
创建型模式
1. 单例模式Singleton
public sealed class Singleton
{//创建一个只读的静态Singleton实例private static readonly Singleton instance new Singleton();// 记录Singleton的创建次数private static int instanceCounter 0;// 单例实例的公共访问点public static Singleton Instance{get{return instance;}}// 私有构造函数private Singleton(){instanceCounter;Console.WriteLine(Instances Created instanceCounter);}// 在此处添加其他的Singleton类方法public void LogMessage(string message){Console.WriteLine(Message: message);}
}
在这个例子中我们有一个名为Singleton的类它有一个私有的构造函数和一个静态的只读属性Instance用于访问Singleton类的唯一实例。我们还有一个LogMessage方法用于模拟Singleton类的某个行为。
以下是一个使用这个Singleton类的控制台应用程序
class Program
{static void Main(string[] args){Singleton fromEmployee Singleton.Instance;fromEmployee.LogMessage(Message from Employee);Singleton fromBoss Singleton.Instance;fromBoss.LogMessage(Message from Boss);Console.ReadLine();}
}
2. 工厂方法模式Factory Method
工厂方法模式是一种创建型设计模式它提供了一种创建对象的接口但允许子类决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。
下面是一个使用C#实现的工厂方法模式的简单示例
// 抽象产品
public interface IProduct
{string Operation();
}// 具体产品A
public class ProductA : IProduct
{public string Operation(){return {Result of ProductA};}
}// 具体产品B
public class ProductB : IProduct
{public string Operation(){return {Result of ProductB};}
}// 抽象创建者
public abstract class Creator
{public abstract IProduct FactoryMethod();
}// 具体创建者A
public class CreatorA : Creator
{public override IProduct FactoryMethod(){return new ProductA();}
}// 具体创建者B
public class CreatorB : Creator
{public override IProduct FactoryMethod(){return new ProductB();}
}
以上代码中定义了两个产品ProductA和ProductB这两个产品都实现了IProduct接口。接着我们有两个Creator类CreatorA和CreatorB它们都继承自抽象基类Creator。CreatorA工厂创建ProductACreatorB工厂创建ProductB。
以下是一个使用这些工厂和产品的示例
class Program
{static void Main(string[] args){// 创建工厂对象Creator creatorA new CreatorA();Creator creatorB new CreatorB();// 通过工厂方法创建产品对象IProduct productA creatorA.FactoryMethod();IProduct productB creatorB.FactoryMethod();// 打印结果Console.WriteLine(ProductA says: productA.Operation());Console.WriteLine(ProductB says: productB.Operation());Console.ReadLine();}
}
当你运行这个程序时它会显示出ProductA和ProductB的Operation方法返回的结果。这说明我们已经成功地使用工厂方法模式创建了产品实例。每个工厂类决定了它创建哪个产品的实例。这种方式使得客户端代码不需要直接实例化产品类而只需要依赖工厂接口增加了程序的灵活性。
3. 抽象工厂模式Abstract Factory
抽象工厂模式是一种创建型设计模式它提供了一种接口用于创建相关或依赖对象的系列而不指定这些对象的具体类。在这个模式中客户端通过他们的抽象接口使用类允许该模式在不影响客户端的情况下替换实现类。
以下是一个简单的抽象工厂模式的C#实现
// 抽象产品动物
public interface IAnimal
{string Speak();
}// 具体产品狗
public class Dog : IAnimal
{public string Speak(){return Bark Bark;}
}// 具体产品猫
public class Cat : IAnimal
{public string Speak(){return Meow Meow;}
}// 抽象工厂
public abstract class IAnimalFactory
{public abstract IAnimal CreateAnimal();
}// 具体工厂狗工厂
public class DogFactory : IAnimalFactory
{public override IAnimal CreateAnimal(){return new Dog();}
}// 具体工厂猫工厂
public class CatFactory : IAnimalFactory
{public override IAnimal CreateAnimal(){return new Cat();}
}
以上代码定义了两种动物Dog和Cat它们都实现了IAnimal接口。然后我们有两个工厂类DogFactory和CatFactory它们都继承自IAnimalFactory。DogFactory生产Dog而CatFactory生产Cat。
以下是一个使用这些工厂和产品的示例
class Program
{static void Main(string[] args){// 创建工厂IAnimalFactory dogFactory new DogFactory();IAnimalFactory catFactory new CatFactory();// 使用工厂创建产品IAnimal dog dogFactory.CreateAnimal();IAnimal cat catFactory.CreateAnimal();// 打印结果Console.WriteLine(Dog says: dog.Speak());Console.WriteLine(Cat says: cat.Speak());Console.ReadLine();}
}
当你运行这个程序时会打印出Dog和Cat的Speak方法的结果这显示了我们已经成功地使用了抽象工厂模式创建了产品实例。这种方式使得客户端代码不需要直接实例化产品类而只需要依赖工厂接口增加了程序的灵活性和扩展性。
4. 建造者模式Builder
建造者模式是一种创建型设计模式它提供了一种创建对象的接口但是允许使用相同的构建过程来创建不同的产品。
以下是在C#中实现建造者模式的一个简单示例
// 产品
public class Car
{public string Engine { get; set; }public string Wheels { get; set; }public string Doors { get; set; }
}// 建造者抽象类
public abstract class CarBuilder
{protected Car car;public void CreateNewCar(){car new Car();}public Car GetCar(){return car;}public abstract void SetEngine();public abstract void SetWheels();public abstract void SetDoors();
}// 具体建造者
public class FerrariBuilder : CarBuilder
{public override void SetEngine(){car.Engine V8;}public override void SetWheels(){car.Wheels 18 inch;}public override void SetDoors(){car.Doors 2;}
}// 指挥者
public class Director
{public Car Construct(CarBuilder carBuilder){carBuilder.CreateNewCar();carBuilder.SetEngine();carBuilder.SetWheels();carBuilder.SetDoors();return carBuilder.GetCar();}
}
以上代码中Car是我们要创建的产品CarBuilder是抽象的建造者定义了制造一个产品所需要的各个步骤FerrariBuilder是具体的建造者实现了CarBuilder定义的所有步骤Director是指挥者它告诉建造者应该按照什么顺序去执行哪些步骤。
以下是一个使用这个建造者模式的示例
class Program
{static void Main(string[] args){Director director new Director();CarBuilder builder new FerrariBuilder();Car ferrari director.Construct(builder);Console.WriteLine($Engine: {ferrari.Engine}, Wheels: {ferrari.Wheels}, Doors: {ferrari.Doors});Console.ReadLine();}
}
当你运行这个程序时会看到我们已经成功地创建了一个Car实例它的各个部分是按照FerrariBuilder所定义的方式创建的。这说明我们使用建造者模式成功地将一个复杂对象的构造过程解耦使得同样的构造过程可以创建不同的表示。
5. 原型模式Prototype
原型模式是一种创建型设计模式它实现了一个原型接口该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时则采用这种模式。例如一个对象需要在一个高代价的数据库操作后被创建。
以下是在C#中实现原型模式的一个简单示例
// 抽象原型
public interface IPrototype
{IPrototype Clone();
}// 具体原型
public class ConcretePrototype : IPrototype
{public string Name { get; set; }public int Value { get; set; }public IPrototype Clone(){// 实现深拷贝return (ConcretePrototype)this.MemberwiseClone(); // Clones the concrete object.}
}
以上代码定义了一个ConcretePrototype类它实现了IPrototype接口。接口定义了一个Clone方法用于复制对象。在ConcretePrototype类中我们使用了MemberwiseClone方法来创建一个新的克隆对象。
以下是一个使用原型模式的示例
class Program
{static void Main(string[] args){ConcretePrototype prototype new ConcretePrototype();prototype.Name Original;prototype.Value 10;Console.WriteLine(Original instance: prototype.Name , prototype.Value);ConcretePrototype clone (ConcretePrototype)prototype.Clone();Console.WriteLine(Cloned instance: clone.Name , clone.Value);Console.ReadLine();}
}
在这个例子中我们创建了一个ConcretePrototype对象并为其属性赋值然后我们调用Clone方法创建了一个新的ConcretePrototype对象。当我们运行这个程序时会看到原始对象和克隆对象的属性是相同的这表明我们已经成功地克隆了一个对象。
执行流程如下 创建一个具体的原型对象为其属性赋值。 调用原型对象的Clone方法创建一个新的对象该对象的属性与原型对象的属性相同。 打印原型对象和克隆对象的属性验证它们是否相同。
结构型模式 6. 适配器模式Adapter
1. 桥接模式Bridge
桥接模式是一种结构型设计模式用于将抽象部分与其实现部分分离使它们都可以独立地变化。
以下是在C#中实现桥接模式的一个简单示例
// 实现类接口
public interface IImplementor
{void OperationImp();
}// 具体实现类A
public class ConcreteImplementorA : IImplementor
{public void OperationImp(){Console.WriteLine(Concrete Implementor A);}
}// 具体实现类B
public class ConcreteImplementorB : IImplementor
{public void OperationImp(){Console.WriteLine(Concrete Implementor B);}
}// 抽象类
public abstract class Abstraction
{protected IImplementor implementor;public Abstraction(IImplementor implementor){this.implementor implementor;}public virtual void Operation(){implementor.OperationImp();}
}// 扩充的抽象类
public class RefinedAbstraction : Abstraction
{public RefinedAbstraction(IImplementor implementor) : base(implementor) { }public override void Operation(){Console.WriteLine(Refined Abstraction is calling implementors method:);base.Operation();}
}
在这个代码中Abstraction是抽象类它有一个IImplementor接口的实例通过这个实例调用实现类的方法。RefinedAbstraction是扩充的抽象类它继承自Abstraction。ConcreteImplementorA和ConcreteImplementorB是实现类它们实现了IImplementor接口。
以下是一个使用这个模式的示例
class Program
{static void Main(string[] args){IImplementor implementorA new ConcreteImplementorA();Abstraction abstractionA new RefinedAbstraction(implementorA);abstractionA.Operation();IImplementor implementorB new ConcreteImplementorB();Abstraction abstractionB new RefinedAbstraction(implementorB);abstractionB.Operation();Console.ReadLine();}
}
在这个例子中我们创建了两个实现类的实例然后创建了两个抽象类的实例每个抽象类的实例都有一个实现类的实例。当我们调用抽象类的Operation方法时它会调用实现类的OperationImp方法。
执行流程如下 创建实现类的实例。 创建抽象类的实例抽象类的实例有一个实现类的实例。 调用抽象类的Operation方法该方法会调用实现类的OperationImp方法。
2. 组合模式Composite
组合模式Composite pattern是一种结构型设计模式它可以使你将对象组合成树形结构并且能像使用独立对象一样使用它们。这种模式的主要目的是使单个对象和组合对象具有一致性。
以下是在C#中实现组合模式的一个简单示例
// 抽象组件类
public abstract class Component
{protected string name;public Component(string name){this.name name;}public abstract void Add(Component c);public abstract void Remove(Component c);public abstract void Display(int depth);
}// 叶节点类
public class Leaf : Component
{public Leaf(string name) : base(name) { }public override void Add(Component c){Console.WriteLine(Cannot add to a leaf);}public override void Remove(Component c){Console.WriteLine(Cannot remove from a leaf);}public override void Display(int depth){Console.WriteLine(new String(-, depth) name);}
}// 构件容器类
public class Composite : Component
{private ListComponent _children new ListComponent();public Composite(string name) : base(name) { }public override void Add(Component component){_children.Add(component);}public override void Remove(Component component){_children.Remove(component);}public override void Display(int depth){Console.WriteLine(new String(-, depth) name);// 显示每个节点的子节点foreach (Component component in _children){component.Display(depth 2);}}
}
在这个代码中Component是组件抽象类它有一个名字并定义了添加、删除和显示操作。Leaf是叶子节点它实现了Component的操作。Composite是组件容器它可以添加、删除和显示其子节点。
以下是一个使用这个模式的示例
class Program
{static void Main(string[] args){Composite root new Composite(root);root.Add(new Leaf(Leaf A));root.Add(new Leaf(Leaf B));Composite comp new Composite(Composite X);comp.Add(new Leaf(Leaf XA));comp.Add(new Leaf(Leaf XB));root.Add(comp);Composite comp2 new Composite(Composite XY);comp2.Add(new Leaf(Leaf XYA));comp2.Add(new Leaf(Leaf XYB));comp.Add(comp2);root.Add(new Leaf(Leaf C));// 在组合中添加和删除Leaf leaf new Leaf(Leaf D);root.Add(leaf);root.Remove(leaf);// 显示树形结构root.Display(1);Console.ReadLine();}
}
在这个例子中我们创建了一个根节点并在其中添加了两个叶子节点。然后我们创建了一个复合节点并在其中添加了两个叶子节点然后我们把复合节点添加到根节点中。我们还在复合节点中添加了另一个复合节点。最后我们又在根节点中添加和删除了一个叶子节点然后显示了树的结构。
执行流程如下 创建组合和叶子对象。 通过调用组合对象的Add方法将叶子对象和其他组合对象添加到组合对象中。 通过调用组合对象的Remove方法将叶子对象从组合对象中移除。 调用组合对象的Display方法显示组合对象的结构。
3. 装饰模式Decorator
装饰模式是一种结构型设计模式它允许在运行时动态地将功能添加到对象中这种模式提供了比继承更有弹性的解决方案。
以下是在C#中实现装饰模式的一个简单示例
// 抽象组件
public abstract class Component
{public abstract string Operation();
}// 具体组件
public class ConcreteComponent : Component
{public override string Operation(){return ConcreteComponent;}
}// 抽象装饰器
public abstract class Decorator : Component
{protected Component component;public Decorator(Component component){this.component component;}public override string Operation(){if (component ! null){return component.Operation();}else{return string.Empty;}}
}// 具体装饰器A
public class ConcreteDecoratorA : Decorator
{public ConcreteDecoratorA(Component comp) : base(comp) { }public override string Operation(){return $ConcreteDecoratorA({base.Operation()});}
}// 具体装饰器B
public class ConcreteDecoratorB : Decorator
{public ConcreteDecoratorB(Component comp) : base(comp) { }public override string Operation(){return $ConcreteDecoratorB({base.Operation()});}
}
在这个代码中Component是一个抽象组件它定义了一个Operation方法。ConcreteComponent是具体组件它实现了Component的Operation方法。Decorator是一个抽象装饰器它包含一个Component对象并重写了Operation方法。ConcreteDecoratorA和ConcreteDecoratorB是具体的装饰器它们继承了Decorator并重写了Operation方法以添加新的功能。
以下是一个使用这个模式的示例
class Program
{static void Main(string[] args){// 基本组件Component component new ConcreteComponent();Console.WriteLine(Basic Component: component.Operation());// 装饰后的组件Component decoratorA new ConcreteDecoratorA(component);Console.WriteLine(A Decorated: decoratorA.Operation());Component decoratorB new ConcreteDecoratorB(decoratorA);Console.WriteLine(B Decorated: decoratorB.Operation());Console.ReadLine();}
}
在这个例子中我们首先创建了一个ConcreteComponent对象并调用它的Operation方法。然后我们创建了一个ConcreteDecoratorA对象它装饰了ConcreteComponent并调用它的Operation方法。最后我们创建了一个ConcreteDecoratorB对象它装饰了ConcreteDecoratorA并调用它的Operation方法。这样我们就可以在运行时动态地添加功能。
执行流程如下 创建一个具体组件对象并调用其操作。 创建一个装饰器对象该对象装饰了具体组件并调用其操作。在操作中装饰器首先调用具体组件的操作然后执行额外的操作。 创建另一个装饰器对象装饰前一个装饰器并调用其操作。在操作中这个装饰器首先调用前一个装饰器的操作然后执行额外的操作。
4. 外观模式Facade
外观模式是一种结构型设计模式提供了一个统一的接口用来访问子系统中的一群接口。外观模式定义了一个高层接口让子系统更容易使用。
以下是在C#中实现外观模式的一个简单示例
// 子系统A
public class SubSystemA
{public string OperationA(){return SubSystemA, OperationA\n;}
}// 子系统B
public class SubSystemB
{public string OperationB(){return SubSystemB, OperationB\n;}
}// 子系统C
public class SubSystemC
{public string OperationC(){return SubSystemC, OperationC\n;}
}// 外观类
public class Facade
{private SubSystemA a new SubSystemA();private SubSystemB b new SubSystemB();private SubSystemC c new SubSystemC();public string OperationWrapper(){string result Facade initializes subsystems:\n;result a.OperationA();result b.OperationB();result c.OperationC();return result;}
}
在这个代码中SubSystemASubSystemB和SubSystemC都是子系统每个子系统都有一个操作。Facade是一个外观类它封装了对子系统的操作提供了一个统一的接口。
以下是一个使用这个模式的示例
class Program
{static void Main(string[] args){Facade facade new Facade();Console.WriteLine(facade.OperationWrapper());Console.ReadLine();}
}
在这个例子中我们创建了一个Facade对象并调用了它的OperationWrapper方法。这个方法封装了对子系统的操作使得客户端可以不直接操作子系统而是通过外观类操作子系统。
执行流程如下 创建一个外观对象。 通过调用外观对象的方法间接地操作子系统。 子系统的操作被封装在外观对象的方法中客户端不需要直接操作子系统。
5. 享元模式Flyweight
享元模式Flyweight Pattern是一种结构型设计模式该模式主要用于减少创建对象的数量以减少内存占用和提高性能。这种类型的设计模式属于结构型模式它提供了一种减少对象数量从而改善应用所需的对象结构的方式。
以下是在C#中实现享元模式的一个简单示例
// 享元类
public class Flyweight
{private string intrinsicState;// 构造函数public Flyweight(string intrinsicState){this.intrinsicState intrinsicState;}// 业务方法public void Operation(string extrinsicState){Console.WriteLine($Intrinsic State {intrinsicState}, Extrinsic State {extrinsicState});}
}// 享元工厂类
public class FlyweightFactory
{private Dictionarystring, Flyweight flyweights new Dictionarystring, Flyweight();public Flyweight GetFlyweight(string key){if (!flyweights.ContainsKey(key)){flyweights[key] new Flyweight(key);}return flyweights[key];}public int GetFlyweightCount(){return flyweights.Count;}
}
在这个代码中Flyweight是享元类它有一个内在状态intrinsicState这个状态是不变的。FlyweightFactory是享元工厂类它维护了一个享元对象的集合。
以下是一个使用这个模式的示例
class Program
{static void Main(string[] args){FlyweightFactory factory new FlyweightFactory();Flyweight flyweightA factory.GetFlyweight(A);flyweightA.Operation(A operation);Flyweight flyweightB factory.GetFlyweight(B);flyweightB.Operation(B operation);Flyweight flyweightC factory.GetFlyweight(A);flyweightC.Operation(C operation);Console.WriteLine($Total Flyweights: {factory.GetFlyweightCount()});Console.ReadLine();}
}
在这个例子中我们创建了一个FlyweightFactory对象并通过它创建了两个享元对象。注意当我们试图创建第三个享元对象时工厂实际上返回了第一个享元对象的引用因为这两个对象的内在状态是相同的。
执行流程如下 创建一个享元工厂对象。 通过享元工厂获取享元对象。如果对象已经存在则返回现有对象否则创建新对象。 执行享元对象的操作。 显示当前享元对象的数量。
6. 代理模式Proxy
代理模式是一种结构型设计模式它提供了一个对象代替另一个对象来控制对它的访问。代理对象可以在客户端和目标对象之间起到中介的作用并添加其他的功能。
以下是在C#中实现代理模式的一个简单示例
// 抽象主题接口
public interface ISubject
{void Request();
}// 真实主题
public class RealSubject : ISubject
{public void Request(){Console.WriteLine(RealSubject: Handling Request.);}
}// 代理
public class Proxy : ISubject
{private RealSubject _realSubject;public Proxy(RealSubject realSubject){this._realSubject realSubject;}public void Request(){if (this.CheckAccess()){this._realSubject.Request();this.LogAccess();}}public bool CheckAccess(){// 检查是否有权限访问Console.WriteLine(Proxy: Checking access prior to firing a real request.);return true;}public void LogAccess(){// 记录请求Console.WriteLine(Proxy: Logging the time of request.);}
}
在这个代码中ISubject是一个接口定义了Request方法。RealSubject是实现了ISubject接口的类Proxy是代理类它也实现了ISubject接口并持有一个RealSubject对象的引用。
以下是一个使用这个模式的示例
class Program
{static void Main(string[] args){Console.WriteLine(Client: Executing the client code with a real subject:);RealSubject realSubject new RealSubject();realSubject.Request();Console.WriteLine();Console.WriteLine(Client: Executing the same client code with a proxy:);Proxy proxy new Proxy(realSubject);proxy.Request();Console.ReadLine();}
}
在这个例子中我们首先直接调用了RealSubject的Request方法然后我们通过代理调用了相同的方法。注意在通过代理调用Request方法时代理还执行了其他的操作如检查访问权限和记录日志。
执行流程如下 创建一个真实主题对象并直接调用其Request方法。 创建一个代理对象代理对象包含一个真实主题的引用。 通过代理对象调用Request方法。在这个方法中代理首先检查访问权限然后调用真实主题的Request方法最后记录日志。
行为型模式 13. 责任链模式Chain of Responsibility
1. 命令模式Command
命令模式Command Pattern是一种数据驱动的设计模式它属于行为型模式。在命令模式中请求在对象中封装成为一个操作或行为这些请求被送到调用对象调用对象寻找可以处理该命令的合适的对象并把命令直接送达到对应的对象该对象会执行这些命令。
以下是在C#中实现命令模式的一个简单示例
// 命令接口
public interface ICommand
{void Execute();
}// 具体命令类
public class ConcreteCommand : ICommand
{private Receiver receiver;public ConcreteCommand(Receiver receiver){this.receiver receiver;}public void Execute(){receiver.Action();}
}// 接收者类
public class Receiver
{public void Action(){Console.WriteLine(Receiver performs an action);}
}// 调用者或发送者类
public class Invoker
{private ICommand command;public void SetCommand(ICommand command){this.command command;}public void ExecuteCommand(){command.Execute();}
}
在这个代码中ICommand是命令接口定义了Execute方法。ConcreteCommand是具体的命令类它实现了ICommand接口并持有一个Receiver对象的引用。Invoker是调用者或发送者类它持有一个ICommand对象的引用并可以通过SetCommand方法设置命令通过ExecuteCommand方法执行命令。
以下是一个使用这个模式的示例
class Program
{static void Main(string[] args){Receiver receiver new Receiver();ICommand command new ConcreteCommand(receiver);Invoker invoker new Invoker();invoker.SetCommand(command);invoker.ExecuteCommand();Console.ReadLine();}
}
在这个例子中我们创建了一个Receiver对象、一个ConcreteCommand对象和一个Invoker对象。然后我们通过Invoker的SetCommand方法设置了命令并通过ExecuteCommand方法执行了命令。
执行流程如下 创建一个接收者对象。 创建一个具体命令对象并将接收者对象传递给它。 创建一个调用者或发送者对象。 通过调用者对象的SetCommand方法设置命令。 通过调用者对象的ExecuteCommand方法执行命令。
2. 解释器模式Interpreter
解释器模式Interpreter Pattern是一种行为型设计模式用于解决一些固定语法格式的需求。它定义了如何在语言中表示和解析语法。
以下是在C#中实现解释器模式的一个简单示例
// 抽象表达式
public interface IExpression
{bool Interpret(string context);
}// 终结符表达式
public class TerminalExpression : IExpression
{private string data;public TerminalExpression(string data){this.data data;}public bool Interpret(string context){if (context.Contains(data)){return true;}return false;}
}// 非终结符表达式
public class OrExpression : IExpression
{private IExpression expr1 null;private IExpression expr2 null;public OrExpression(IExpression expr1, IExpression expr2){this.expr1 expr1;this.expr2 expr2;}public bool Interpret(string context){return expr1.Interpret(context) || expr2.Interpret(context);}
}
在这个代码中IExpression是抽象表达式定义了Interpret方法。TerminalExpression是终结符表达式它实现了IExpression接口。OrExpression是非终结符表达式它也实现了IExpression接口。
以下是一个使用这个模式的示例
class Program
{static void Main(string[] args){IExpression isMale GetMaleExpression();IExpression isMarriedWoman GetMarriedWomanExpression();Console.WriteLine($John is male? {isMale.Interpret(John)});Console.WriteLine($Julie is a married women? {isMarriedWoman.Interpret(Married Julie)});Console.ReadLine();}// 规则Robert 和 John 是男性public static IExpression GetMaleExpression(){IExpression robert new TerminalExpression(Robert);IExpression john new TerminalExpression(John);return new OrExpression(robert, john);}// 规则Julie 是一个已婚的女性public static IExpression GetMarriedWomanExpression(){IExpression julie new TerminalExpression(Julie);IExpression married new TerminalExpression(Married);return new OrExpression(julie, married);}
}
在这个例子中我们定义了两个规则Robert和John是男性和Julie是一个已婚的女性。我们然后创建了两个表达式对象分别表示这两个规则并使用这两个对象来解析输入。
执行流程如下 创建终结符表达式对象和非终结符表达式对象用于表示规则。 调用表达式对象的Interpret方法解析输入的字符串。 输出解析结果。
3. 迭代器模式Iterator
迭代器模式Iterator Pattern是一种行为型设计模式它提供了一种方法来访问一个对象的元素而不需要暴露该对象的内部表示。以下是在C#中实现迭代器模式的一个简单示例
// 抽象聚合类
public interface IAggregate
{IIterator CreateIterator();void Add(string item);int Count { get; }string this[int index] { get; set; }
}// 具体聚合类
public class ConcreteAggregate : IAggregate
{private Liststring items new Liststring();public IIterator CreateIterator(){return new ConcreteIterator(this);}public int Count{get { return items.Count; }}public string this[int index]{get { return items[index]; }set { items.Insert(index, value); }}public void Add(string item){items.Add(item);}
}// 抽象迭代器
public interface IIterator
{string First();string Next();bool IsDone { get; }string CurrentItem { get; }
}// 具体迭代器
public class ConcreteIterator : IIterator
{private ConcreteAggregate aggregate;private int current 0;public ConcreteIterator(ConcreteAggregate aggregate){this.aggregate aggregate;}public string First(){return aggregate[0];}public string Next(){string ret null;if (current aggregate.Count - 1){ret aggregate[current];}return ret;}public string CurrentItem{get { return aggregate[current]; }}public bool IsDone{get { return current aggregate.Count; }}
}
在这个代码中IAggregate是抽象聚合类定义了CreateIterator等方法ConcreteAggregate是具体聚合类实现了IAggregate接口。IIterator是抽象迭代器定义了First、Next等方法ConcreteIterator是具体迭代器实现了IIterator接口。
以下是一个使用这个模式的示例
class Program
{static void Main(string[] args){IAggregate aggregate new ConcreteAggregate();aggregate.Add(Item A);aggregate.Add(Item B);aggregate.Add(Item C);aggregate.Add(Item D);IIterator iterator aggregate.CreateIterator();Console.WriteLine(Iterating over collection:);string item iterator.First();while (item ! null){Console.WriteLine(item);item iterator.Next();}Console.ReadLine();}
}
在这个例子中我们创建了一个ConcreteAggregate对象并添加了几个元素。然后我们通过CreateIterator方法创建了一个迭代器并使用这个迭代器遍历了集合中的所有元素。
执行流程如下 创建一个聚合对象并添加一些元素。 通过聚合对象的CreateIterator方法创建一个迭代器。 通过迭代器的First方法获取第一个元素然后通过Next方法获取后续的元素直到获取不到元素为止。
4. 中介者模式Mediator
中介者模式是一种行为设计模式它让你能减少一组对象之间复杂的通信。它提供了一个中介者对象此对象负责在组中的对象之间进行通信而不是这些对象直接进行通信。
首先让我们定义一个中介者接口和一个具体的中介者
// Mediator 接口声明了与组件交互的方法。
public interface IMediator
{void Notify(object sender, string ev);
}// 具体 Mediators 实现协作行为它负责协调多个组件。
public class ConcreteMediator : IMediator
{private Component1 _component1;private Component2 _component2;public ConcreteMediator(Component1 component1, Component2 component2){_component1 component1;_component1.SetMediator(this);_component2 component2;_component2.SetMediator(this);}public void Notify(object sender, string ev){if (ev A){Console.WriteLine(Mediator reacts on A and triggers following operations:);this._component2.DoC();}if (ev D){Console.WriteLine(Mediator reacts on D and triggers following operations:);this._component1.DoB();this._component2.DoC();}}
}
接着我们定义一个基础组件类和两个具体组件
public abstract class BaseComponent
{protected IMediator _mediator;public BaseComponent(IMediator mediator null){_mediator mediator;}public void SetMediator(IMediator mediator){this._mediator mediator;}
}// 具体 Components 实现各种功能。它们不依赖于其他组件。
// 它们也不依赖于任何具体 Mediator 类。
public class Component1 : BaseComponent
{public void DoA(){Console.WriteLine(Component 1 does A.);this._mediator.Notify(this, A);}public void DoB(){Console.WriteLine(Component 1 does B.);this._mediator.Notify(this, B);}
}public class Component2 : BaseComponent
{public void DoC(){Console.WriteLine(Component 2 does C.);this._mediator.Notify(this, C);}public void DoD(){Console.WriteLine(Component 2 does D.);this._mediator.Notify(this, D);}
}
最后我们来创建一个客户端代码
class Program
{static void Main(string[] args){// The client code.Component1 component1 new Component1();Component2 component2 new Component2();new ConcreteMediator(component1, component2);Console.WriteLine(Client triggers operation A.);component1.DoA();Console.WriteLine();Console.WriteLine(Client triggers operation D.);component2.DoD();}
}
这个示例中的各个组件通过中介者来进行通信而不是直接通信这样就可以减少组件之间的依赖性使得它们可以更容易地被独立修改。当一个组件发生某个事件例如Component 1 does A时它会通过中介者来通知其他组件这样其他组件就可以根据这个事件来做出响应例如Component 2 does C。
5. 备忘录模式Memento
备忘录模式是一种行为设计模式它能保存对象的状态以便在后面可以恢复它。在大多数情况下这种模式可以让你在不破坏对象封装的前提下保存和恢复对象的历史状态。
以下是一个简单的备忘录模式的实现其中有三个主要的类Originator保存了一个重要的状态这个状态可能会随着时间改变Memento保存了Originator的一个快照这个快照包含了Originator的状态以及Caretaker负责保存Memento。
// Originator 类可以生成一个备忘录并且可以通过备忘录恢复其状态。
public class Originator
{private string _state;public Originator(string state){this._state state;Console.WriteLine($Originator: My initial state is: {_state});}public void DoSomething(){Console.WriteLine(Originator: Im doing something important.);_state GenerateRandomString(30);Console.WriteLine($Originator: and my state has changed to: {_state});}private string GenerateRandomString(int length 10){string allowedSymbols abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ;string result string.Empty;while (length 0){result allowedSymbols[new Random().Next(0, allowedSymbols.Length)];length--;}return result;}public IMemento Save(){return new ConcreteMemento(_state);}public void Restore(IMemento memento){_state memento.GetState();Console.WriteLine($Originator: My state has changed to: {_state});}
}// 备忘录接口提供了获取备忘录和原发器状态的方法。但在该接口中并未声明所有的方法一些方法只在原发器中声明。
public interface IMemento
{string GetName();string GetState();DateTime GetDate();
}// Concrete Memento 存储原发器状态并通过原发器实现备份。备忘录是不可变的因此没有 set 方法。
public class ConcreteMemento : IMemento
{private string _state;private DateTime _date;public ConcreteMemento(string state){_state state;_date DateTime.Now;}public string GetState(){return _state;}public string GetName(){return ${_date} / ({_state.Substring(0, 9)})...;}public DateTime GetDate(){return _date;}
}// Caretaker 不依赖于具体备忘录类。结果它不会有任何访问原发器状态的权利它只能获取备忘录的元数据。
public class Caretaker
{private ListIMemento _mementos new ListIMemento();private Originator _originator null;public Caretaker(Originator originator){this._originator originator;}public void Backup(){Console.WriteLine(\nCaretaker: Saving Originators state...);_mementos.Add(_originator.Save());}public void Undo(){if (_mementos.Count 0){return;}var memento _mementos.Last();_mementos.Remove(memento);Console.WriteLine(Caretaker: Restoring state to: memento.GetName());try{_originator.Restore(memento);}catch (Exception){Undo();}}public void ShowHistory(){Console.WriteLine(Caretaker: Heres the list of mementos:);foreach (var memento in _mementos){Console.WriteLine(memento.GetName());}}
}// 客户端代码
class Program
{static void Main(string[] args){Originator originator new Originator(Super-duper-super-puper-super.);Caretaker caretaker new Caretaker(originator);caretaker.Backup();originator.DoSomething();caretaker.Backup();originator.DoSomething();caretaker.Backup();originator.DoSomething();Console.WriteLine();caretaker.ShowHistory();Console.WriteLine(\nClient: Now, lets rollback!\n);caretaker.Undo();Console.WriteLine(\nClient: Once more!\n);caretaker.Undo();}
}
以上的代码中Originator 持有一些重要的状态并且提供了方法去保存它的状态到一个备忘录对象以及从备忘录对象中恢复它的状态。Caretaker 负责保存备忘录但是它不能操作备忘录对象中的状态。当用户执行操作时我们先保存当前的状态然后执行操作。如果用户后来不满意新的状态他们可以方便地从旧的备忘录中恢复状态。
6. 观察者模式Observer
观察者模式Observer Pattern是一种行为型设计模式当一个对象的状态发生变化时依赖它的所有对象都会得到通知并被自动更新。以下是在C#中实现观察者模式的一个简单示例
// 抽象观察者
public interface IObserver
{void Update();
}// 具体观察者
public class ConcreteObserver : IObserver
{private string name;public ConcreteObserver(string name){this.name name;}public void Update(){Console.WriteLine(${name} received an update!);}
}// 抽象主题
public interface ISubject
{void RegisterObserver(IObserver observer);void RemoveObserver(IObserver observer);void NotifyObservers();
}// 具体主题
public class ConcreteSubject : ISubject
{private ListIObserver observers new ListIObserver();public void RegisterObserver(IObserver observer){observers.Add(observer);}public void RemoveObserver(IObserver observer){if (observers.Contains(observer)){observers.Remove(observer);}}public void NotifyObservers(){foreach (var observer in observers){observer.Update();}}public void ChangeState(){// 触发状态变化通知所有观察者NotifyObservers();}
}
在这个代码中IObserver是抽象观察者定义了Update方法ConcreteObserver是具体观察者实现了IObserver接口。ISubject是抽象主题定义了RegisterObserver、RemoveObserver和NotifyObservers方法ConcreteSubject是具体主题实现了ISubject接口。
以下是一个使用这个模式的示例
class Program
{static void Main(string[] args){ConcreteSubject subject new ConcreteSubject();subject.RegisterObserver(new ConcreteObserver(Observer 1));subject.RegisterObserver(new ConcreteObserver(Observer 2));subject.RegisterObserver(new ConcreteObserver(Observer 3));subject.ChangeState();Console.ReadLine();}
}
在这个例子中我们创建了一个ConcreteSubject对象并注册了三个观察者。然后我们通过ChangeState方法改变了主题的状态这会触发主题通知所有观察者。
执行流程如下 创建一个具体主题对象。 创建几个具体观察者对象并通过主题的RegisterObserver方法将这些观察者注册到主题中。 通过主题的ChangeState方法改变主题的状态这会触发主题通知所有观察者。
7. 状态模式State
状态模式在面向对象编程中是一种允许对象在其内部状态改变时改变其行为的设计模式。这种类型的设计模式属于行为型模式。在状态模式中我们创建对象表示各种状态以及一个行为随状态改变而改变的上下文对象。
以下是一个状态模式的示例。这个示例中我们将创建一个银行账户它有两个状态正常状态NormalState和透支状态OverdrawnState。当用户执行操作存款和取款时账户状态将相应地进行更改。
首先我们定义一个表示状态的接口
public interface IAccountState
{void Deposit(Action addToBalance);void Withdraw(Action subtractFromBalance);void ComputeInterest();
}
然后我们创建两个表示具体状态的类
public class NormalState : IAccountState
{public void Deposit(Action addToBalance){addToBalance();Console.WriteLine(Deposit in NormalState);}public void Withdraw(Action subtractFromBalance){subtractFromBalance();Console.WriteLine(Withdraw in NormalState);}public void ComputeInterest(){Console.WriteLine(Interest computed in NormalState);}
}public class OverdrawnState : IAccountState
{public void Deposit(Action addToBalance){addToBalance();Console.WriteLine(Deposit in OverdrawnState);}public void Withdraw(Action subtractFromBalance){Console.WriteLine(No withdraw in OverdrawnState);}public void ComputeInterest(){Console.WriteLine(Interest and fees computed in OverdrawnState);}
}
然后我们创建一个Context类它使用这些状态来执行其任务
public class BankAccount
{private IAccountState _state;private double _balance;public BankAccount(IAccountState state){_state state;_balance 0;}public void Deposit(double amount){_state.Deposit(() _balance amount);StateChangeCheck();}public void Withdraw(double amount){_state.Withdraw(() _balance - amount);StateChangeCheck();}public void ComputeInterest(){_state.ComputeInterest();}private void StateChangeCheck(){if (_balance 0.0)_state new OverdrawnState();else_state new NormalState();}
}
现在你可以创建一个实例并运行一个Demo来测试这个状态模式的代码
public class Program
{public static void Main(string[] args){var account new BankAccount(new NormalState());account.Deposit(1000); // Deposit in NormalStateaccount.Withdraw(2000); // Withdraw in NormalState; No withdraw in OverdrawnStateaccount.Deposit(100); // Deposit in OverdrawnStateaccount.ComputeInterest(); // Interest and fees computed in OverdrawnStateConsole.ReadKey();}
}
这个程序首先在正常状态下进行存款操作然后尝试进行取款操作。由于取款金额超过账户余额所以账户进入透支状态并阻止进一步的取款操作。但存款仍然被允许以使账户回归到正常状态。计算利息的行为也根据账户的状态变化而变化。
8. 策略模式Strategy
策略模式定义了一系列的算法并将每一个算法封装起来使得它们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
以下是一个简单的策略模式的C#实现。这个例子中我们将创建一个排序策略比如快速排序和冒泡排序它们实现同一个接口然后创建一个Context类它使用这些策略来执行排序操作。
首先我们定义一个表示排序策略的接口
public interface ISortStrategy
{void Sort(Listint list);
}
然后我们创建两个表示具体策略的类
public class QuickSort : ISortStrategy
{public void Sort(Listint list){list.Sort(); // Quick sort is in-place but here we are using built-in methodConsole.WriteLine(QuickSorted list );}
}public class BubbleSort : ISortStrategy
{public void Sort(Listint list){int n list.Count;for (int i 0; i n - 1; i)for (int j 0; j n - i - 1; j)if (list[j] list[j 1]){// swap temp and list[i]int temp list[j];list[j] list[j 1];list[j 1] temp;}Console.WriteLine(BubbleSorted list );}
}
然后我们创建一个Context类它使用这些策略来执行其任务
public class SortedList
{private Listint _list new Listint();private ISortStrategy _sortstrategy;public void SetSortStrategy(ISortStrategy sortstrategy){this._sortstrategy sortstrategy;}public void Add(int num){_list.Add(num);}public void Sort(){_sortstrategy.Sort(_list);// Print sorted listforeach (int num in _list){Console.Write(num );}Console.WriteLine();}
}
现在你可以创建一个实例并运行一个Demo来测试这个策略模式的代码
public class Program
{public static void Main(string[] args){SortedList sortedList new SortedList();sortedList.Add(1);sortedList.Add(5);sortedList.Add(3);sortedList.Add(4);sortedList.Add(2);sortedList.SetSortStrategy(new QuickSort());sortedList.Sort(); // Output: QuickSorted list 1 2 3 4 5 sortedList.SetSortStrategy(new BubbleSort());sortedList.Sort(); // Output: BubbleSorted list 1 2 3 4 5 Console.ReadKey();}
}
这个程序首先创建了一个未排序的列表然后它首先使用快速排序策略进行排序接着又使用冒泡排序策略进行排序。
9. 模板方法模式Template Method
模板方法模式定义了一个操作中算法的骨架将这些步骤延迟到子类中。模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
以下是一个模板方法模式的示例。这个示例中我们将创建一个烹饪食物的过程这个过程有一些固定的步骤例如准备材料清理但是具体的烹饪步骤则取决于具体的食物。
首先我们定义一个抽象的模板类
public abstract class CookingProcedure
{// The Template method public void PrepareDish(){PrepareIngredients();Cook();CleanUp();}public void PrepareIngredients(){Console.WriteLine(Preparing the ingredients...);}// These methods will be overridden by subclassespublic abstract void Cook();public void CleanUp(){Console.WriteLine(Cleaning up...);}
}
然后我们创建两个具体的子类它们分别实现了具体的烹饪步骤
public class CookPasta : CookingProcedure
{public override void Cook(){Console.WriteLine(Cooking pasta...);}
}public class BakeCake : CookingProcedure
{public override void Cook(){Console.WriteLine(Baking cake...);}
}
现在你可以创建一个实例并运行一个Demo来测试这个模板方法模式的代码
public class Program
{public static void Main(string[] args){CookingProcedure cookingProcedure new CookPasta();cookingProcedure.PrepareDish();Console.WriteLine();cookingProcedure new BakeCake();cookingProcedure.PrepareDish();Console.ReadKey();}
}
在这个程序中我们首先创建了一个CookPasta对象然后调用其PrepareDish方法。然后我们创建了一个BakeCake对象再次调用其PrepareDish方法。这两个对象虽然具有不同的Cook方法但是它们的PrepareDish方法的结构即算法的骨架是相同的。
10. 访问者模式Visitor
访问者模式Visitor Pattern是一种将算法与对象结构分离的软件设计模式。这种模式的基本想法就是通过所谓的访问者来改变元素的操作。这样一来元素的类可以用于表示元素结构而具体的操作则可以在访问者类中定义。
以下是一个使用C#实现的访问者模式示例包括了详细的注释和执行流程。
这个示例中有三个主要部分访问者IVisitor、可访问元素IElement和元素结构ObjectStructure。同时有具体访问者ConcreteVisitor和具体元素ConcreteElement。
// 访问者接口
public interface IVisitor
{void VisitConcreteElementA(ConcreteElementA concreteElementA);void VisitConcreteElementB(ConcreteElementB concreteElementB);
}// 具体访问者A
public class ConcreteVisitorA : IVisitor
{public void VisitConcreteElementA(ConcreteElementA concreteElementA){Console.WriteLine(${concreteElementA.GetType().Name} is being visited by {this.GetType().Name});}public void VisitConcreteElementB(ConcreteElementB concreteElementB){Console.WriteLine(${concreteElementB.GetType().Name} is being visited by {this.GetType().Name});}
}// 具体访问者B
public class ConcreteVisitorB : IVisitor
{public void VisitConcreteElementA(ConcreteElementA concreteElementA){Console.WriteLine(${concreteElementA.GetType().Name} is being visited by {this.GetType().Name});}public void VisitConcreteElementB(ConcreteElementB concreteElementB){Console.WriteLine(${concreteElementB.GetType().Name} is being visited by {this.GetType().Name});}
}// 元素接口
public interface IElement
{void Accept(IVisitor visitor);
}// 具体元素A
public class ConcreteElementA : IElement
{public void Accept(IVisitor visitor){visitor.VisitConcreteElementA(this);}
}// 具体元素B
public class ConcreteElementB : IElement
{public void Accept(IVisitor visitor){visitor.VisitConcreteElementB(this);}
}// 对象结构
public class ObjectStructure
{private ListIElement _elements new ListIElement();public void Attach(IElement element){_elements.Add(element);}public void Detach(IElement element){_elements.Remove(element);}public void Accept(IVisitor visitor){foreach (var element in _elements){element.Accept(visitor);}}
}
执行流程如下 创建具体元素ConcreteElementA和ConcreteElementB的实例。 创建对象结构ObjectStructure的实例并将步骤1创建的具体元素添加到对象结构中。 创建具体访问者ConcreteVisitorA和ConcreteVisitorB的实例。 调用对象结构的Accept方法传入步骤3创建的具体访问者使具体访问者访问对象结构中的所有元素。
以下是一个使用上述代码的示例
public class Program
{public static void Main(){ObjectStructure objectStructure new ObjectStructure();objectStructure.Attach(new ConcreteElementA());objectStructure.Attach(new ConcreteElementB());ConcreteVisitorA visitorA new ConcreteVisitorA();ConcreteVisitorB visitorB new ConcreteVisitorB();objectStructure.Accept(visitorA);objectStructure.Accept(visitorB);Console.ReadKey();}
}
这个程序会打印出访问者A和访问者B分别访问具体元素A和具体元素B的信息。