.NET C# 开发常用的10种设计模式

.NET C# 开发常用的10种设计模式

设计模式是软件设计中出现的常见问题的可重用解决方案。它们是用于解决设计问题的模板,这些设计问题已被证明在各种情况下都是有效的。它们为开发人员提供了通用词汇和对最佳实践的共同理解,使他们更容易就复杂的设计问题进行沟通和协作。总而言之,它们很重要,因为它们:为常见设计问题提供经过验证的解决方案促进开发人员之间的共同词汇和共识节省创建解决方案的时间和精力推广模块化和可维护的代码库适用于各种设计问题,不受平台或语言限制。设计模式并不特定于任何编程语言或技术。它们适用于任何软件开发项目,无论使用何种平台或语言。单例模式单一实例模式是一种设计模式,它将类限制为只有一个实例,同时提供对此实例的全局访问点。

设计模式是软件设计中出现的常见问题的可重用解决方案。它们是用于解决设计问题的模板,这些设计问题已被证明在各种情况下都是有效的。它们为开发人员提供了通用词汇和对最佳实践的共同理解,使他们更容易就复杂的设计问题进行沟通和协作。

总而言之,它们很重要,因为它们:

为常见设计问题提供经过验证的解决方案

促进开发人员之间的共同词汇和共识

节省创建解决方案的时间和精力

推广模块化和可维护的代码库

适用于各种设计问题,不受平台或语言限制。

设计模式并不特定于任何编程语言或技术。它们适用于任何软件开发项目,无论使用何种平台或语言。

单例模式

单一实例模式是一种设计模式,它将类限制为只有一个实例,同时提供对此实例的全局访问点。当只需要一个类的单个实例来控制整个执行过程中的操作时,将使用此模式。当您需要确保只创建类的一个实例并且可以从应用程序中的单个点访问该实例时,它特别有用。

Singleton 模式最常见的示例之一是 Logger 类。Logger 类用于将日志消息写入文件、数据库或其他存储介质。由于 Logger 类的多个实例将导致多个日志,因此将 Logger 类实现为 Singleton 是有意义的。

另一个示例是数据库连接管理器类,该类可确保在整个应用程序中仅创建和使用数据库连接的一个实例。

若要在 C# 中实现单一实例模式,可以使用以下步骤:

声明私有构造函数:私有构造函数确保不能从类外部实例化类。

声明私有静态实例变量:此变量保存类的单个实例。

声明一个返回类实例的公共静态方法:如果类的实例不存在,则此方法创建该实例,如果该实例存在,则返回现有实例。

下面是 C# 中 Singleton 模式的示例:

public class Singleton

{

private static Singleton instance;

private static readonly object padlock = new object();

private Singleton()

{

}

public static Singleton Instance

{

get

{

if (instance == null)

{

lock (padlock)

{

if (instance == null)

{

instance = new Singleton();

}

}

}

return instance;

}

}

}

在此示例中,该属性使用双重检查的锁定机制来确保只创建类的一个实例,即使在多线程环境中也是如此。

工厂模式

Factory 模式是一种创建设计模式,它提供了用于在超类中创建对象的接口,但允许子类更改将要创建的对象的类型。Factory 模式提供了一种封装对象创建并将其委托给子类的方法。

工厂模式的一个常见示例是形状工厂,它根据用户的输入创建不同类型的形状。例如,可以要求工厂创建一个圆形、正方形或三角形,它将返回相应的形状对象。

另一个例子是 GUI 小部件工厂,它根据用户的请求创建不同类型的小部件(按钮、复选框等)。

若要在 C# 中实现工厂模式,可以使用以下步骤:

定义一个接口,该接口概述了要创建的对象的基本结构。

创建实现接口的具体类,并表示可以创建的不同类型的对象。

创建一个具有用于创建对象的方法的工厂类。此方法接受确定要创建的对象类型的参数,并返回相应的对象。

下面是 C# 中工厂模式的示例:

public interface IShape

{

void Draw();

}

public class Circle : IShape

{

public void Draw()

{

Console.WriteLine("Drawing a Circle");

}

}

public class Square : IShape

{

public void Draw()

{

Console.WriteLine("Drawing a Square");

}

}

public class ShapeFactory

{

public static IShape GetShape(string shapeType)

{

if (shapeType == "Circle")

{

return new Circle();

}

else if (shapeType == "Square")

{

return new Square();

}

else

{

return null;

}

}

}

在此示例中,该类提供了一种用于创建类型为 的对象的方法。该方法接受一个参数,该参数确定要创建的形状类型,并返回相应的对象。

装饰器模式

装饰器模式是一种结构设计模式,允许您在不更改其底层结构的情况下动态添加或扩展对象的行为。它为扩展对象的功能提供了一种灵活的替代方法。

Decorator 模式的一个常见示例是咖啡店,您可以在其中为基本咖啡添加不同的口味和配料。例如,您可以在普通咖啡中加入奶油、糖或糖浆,每次添加都会改变咖啡的风味。

另一个例子是汽车定制商店,您可以在其中为基本汽车模型添加不同的配件。例如,您可以添加天窗、导航系统或音响系统,每次添加都会修改汽车的特性和功能。

若要在 C# 中实现 Decorator 模式,可以使用以下步骤:

定义一个界面,该界面概述了要装饰的对象的基本结构。

创建实现接口并表示对象的不同组件的具体类。

创建具体的修饰器类,这些类通过添加其他行为或职责来扩展对象的功能。这些修饰器类应实现与它们修饰的对象相同的接口。

下面是 C# 中 Decorator 模式的示例:

public interface ICoffee

{

double GetCost();

string GetIngredients();

}

public class BasicCoffee : ICoffee

{

public double GetCost()

{

return 1.0;

}

public string GetIngredients()

{

return "Coffee";

}

}

public abstract class CoffeeDecorator : ICoffee

{

protected ICoffee decoratedCoffee;

public CoffeeDecorator(ICoffee coffee)

{

decoratedCoffee = coffee;

}

public virtual double GetCost()

{

return decoratedCoffee.GetCost();

}

public virtual string GetIngredients()

{

return decoratedCoffee.GetIngredients();

}

}

public class CreamDecorator : CoffeeDecorator

{

public CreamDecorator(ICoffee coffee) : base(coffee)

{

}

public override double GetCost()

{

return decoratedCoffee.GetCost() + 0.5;

}

public override string GetIngredients()

{

return decoratedCoffee.GetIngredients() + ", Cream";

}

}

public class SugarDecorator : CoffeeDecorator

{

public SugarDecorator(ICoffee coffee) : base(coffee)

{

}

public override double GetCost()

{

return decoratedCoffee.GetCost() + 0.2;

}

public override string GetIngredients()

{

return decoratedCoffee.GetIngredients() + ", Sugar";

}

}

观察者模式

观察者设计模式是一种行为模式,它允许对象(称为主体)在其状态发生变化时通知许多其他对象(称为观察者)。该模式对于创建多个对象依赖于另一个对象的状态的系统非常有用,并且需要在状态更改时收到通知。

在 C# 中,可以使用委托和事件来实现 Observer 模式。主题类定义一个事件,观察者类订阅该事件。当主题的状态发生更改时,它会引发事件,并且所有已注册的观察者类都会收到通知。

下面是 C# 中 Observer 模式的简单示例:

public class Subject

{

public delegate void EventHandler(string message);

public event EventHandler Notify;

public void Change(string message)

{

Notify?.Invoke(message);

}

}

public class Observer

{

private string name;

public Observer(string name, Subject subject)

{

this.name = name;

subject.Notify += Update;

}

public void Update(string message)

{

Console.WriteLine($"{name} received: {message}");

}

}

在此示例中,Subject 类定义一个名为 Notify 的事件,该事件的类型为 EventHandler 委托。Observer 类在其构造函数中将字符串名称和 Subject 对象作为参数,并将 Update 方法注册为 Notify 事件的事件处理程序。当使用者引发 Notify 事件并输出收到的消息时,将调用 Update 方法。

Subject 类的 Change 方法用于更改主题的状态并引发 Notify 事件,通知所有已注册的观察者类。在 Change 方法中使用运算符,以确保仅在有订阅者时引发事件。

此示例演示如何使用 Observer 模式创建一个系统,在该系统中,可以通知多个对象另一个对象的状态更改,而不必紧密耦合这些对象。该模式提供了一种灵活且可维护的方式,通过允许多个观察者收到对单个主题的更改的通知,来实现对象之间的通信并促进代码重用。

适配器模式

适配器模式是一种结构模式,它允许一个对象适应另一个对象的接口。当两个对象具有不兼容的接口,但其中一个对象需要由另一个对象使用时,该模式很有用。

在 C# 中,可以通过创建一个适配器类来实现适配器模式,该类包装目标对象并公开兼容的接口。适配器类实现所需的接口,并将调用委托给目标对象。

下面是 C# 中适配器模式的简单示例:

public interface ITarget

{

void Request();

}

public class Adaptee

{

public void SpecificRequest()

{

Console.WriteLine("Specific Request");

}

}

public class Adapter : ITarget

{

private Adaptee adaptee;

public Adapter(Adaptee adaptee)

{

this.adaptee = adaptee;

}

public void Request()

{

adaptee.SpecificRequest();

}

}

在此示例中,ITarget 接口使用 Request 方法定义目标对象所需的接口。Adaptee 类使用 SpecificRequest 方法定义特定接口。Adapter 类实现 ITarget 接口,并将 Adaptee 对象作为其构造函数中的参数。Adapter 类的 Request 方法将调用委托给 Adaptee 类的 SpecificRequest 方法。

此示例演示如何使用 Adapter 模式为两个接口不兼容的对象创建兼容接口。该模式提供了一种灵活且可维护的方式,通过允许客户端通过适配器使用目标对象来使对象相互适应并促进代码重用。

立面模式

立面模式是一种结构设计模式,它为复杂系统提供了简化的接口。该模式用于隐藏系统的复杂性,并为客户端提供统一且易于使用的界面。

在 C# 中,可以通过创建一个 Facade 类来实现 Facade 模式,该类向复杂系统公开一个简化的接口。Facade 类封装了系统的复杂性,并向客户端公开了一个简单直观的界面。

下面是 C# 中 Facade 模式的简单示例:

public class SubSystemA

{

public void MethodA()

{

Console.WriteLine("SubSystemA MethodA");

}

}

public class SubSystemB

{

public void MethodB()

{

Console.WriteLine("SubSystemB MethodB");

}

}

public class Facade

{

private SubSystemA subSystemA;

private SubSystemB subSystemB;

public Facade()

{

subSystemA = new SubSystemA();

subSystemB = new SubSystemB();

}

public void Method()

{

Console.WriteLine("Facade Method");

subSystemA.MethodA();

subSystemB.MethodB();

}

}

在此示例中,SubSystemA 和 SubSystemB 类表示 Facade 类旨在简化的复杂系统。Facade 类负责处理系统的复杂性,并通过其 Method 为客户端提供统一和简化的接口。调用 Method 时,它将调用 SubSystemA 类的 MethodA 和 SubSystemB 类的 MethodB。

Facade 模式有助于简化客户端与复杂系统的交互,并减少客户端与系统之间的耦合。通过提供简化的界面,Facade 模式使客户端更容易与系统交互,并降低错误和维护问题的风险。

命令模式

命令模式是一种行为设计模式,它将请求转换为对象,允许客户端参数化和排队请求,并允许在不同时间对请求进行排队和执行。如果希望能够对对象执行操作,但希望将实际操作与将执行操作的对象分开,则命令模式非常有用。

考虑一个场景,您有一个电视遥控器,并且想要更改频道。命令模式允许您向电视发送命令以更改频道,而无需知道如何更改频道的具体实现。

在此示例中,命令接口是为所有命令设置标准的基础:

public interface ICommand

{

void Execute();

}

接下来,可以为希望能够执行的每个操作创建 Command 接口的具体实现:

public class ChangeChannelCommand : ICommand

{

private readonly Television _television;

private readonly int _channel;

public ChangeChannelCommand(Television television, int channel)

{

_television = television;

_channel = channel;

}

public void Execute()

{

_television.ChangeChannel(_channel);

}

}

最后,可以创建一个将执行以下命令的类:

public class RemoteControl

{

private readonly ICommand _command;

public RemoteControl(ICommand command)

{

_command = command;

}

public void PressButton()

{

_command.Execute();

}

}

使用命令模式,可以将要执行的操作与将执行操作的对象分开,从而实现更灵活的模块化设计。

抽象工厂模式

抽象工厂模式是一种创建设计模式,它提供了一个接口,用于创建相关或依赖对象的族,而无需指定其具体类。

抽象工厂可以被视为创建对象系列的蓝图。抽象工厂定义了一组用于创建对象的方法,但将实例化的实际具体类的选择权留给了具体工厂子类。

下面是 C# 中的一个示例,用于演示抽象工厂模式:

public abstract AbstractVehicleFactory

{

public abstract IBody CreateBody();

public abstract IChassis CreateChassis();

public abstract IWindows CreateWindows();

}

public class CarFactory : AbstractVehicleFactory

{ public override IBody CreateBody()

{

return new CarBody();

public override IChassis CreateChassis()

{

return new CarChassis();

public override IWindows CreateWindows()

{

return new CarWindows();

}

public class TruckFactory : AbstractVehicleFactory

{ public override IBody CreateBody()

{

return new TruckBody();

public override IChassis CreateChassis()

{

return new TruckChassis();

public override IWindows CreateWindows()

{

return new TruckWindows();

}

public interface IBody { }public interface IChassis { }public interface IWindows { }public class CarBody : IBody { }

public class CarChassis : IChassis { }

public class CarWindows : IWindows { }public class TruckBody : IBody { }public class TruckChassis : IChassis { }

public class TruckWindows : IWindows { }

在上面的例子中,我们有两个混凝土工厂,和 ,它们实现了接口。这些工厂分别提供了创建与汽车和卡车相关的对象的方法。通过使用抽象工厂,我们可以创建一整套相关对象,例如车身、汽车底盘、车窗、卡车车身、卡车底盘和卡车车窗,而无需指定要实例化的确切类。

当我们需要创建一组属于同一系列且结构相似但实现细节不同的对象时,抽象工厂模式会很有用。通过使用抽象工厂,我们可以封装对象的创建,并使我们的代码更加灵活和可维护。

生成器模式

构建器设计模式是一种创建设计模式,它提供了一种以增量方式构建复杂对象的方法。Builder 模式背后的主要思想是将复杂对象的构造与其表示分开,允许相同的构造过程创建不同的表示。

在面向对象编程中,构建器是帮助创建其他对象(通常是复杂对象)的对象。它提供了用于创建对象的更高级别的接口,从而可以更轻松地创建具有多个变量、分阶段构建或由多个对象组成的对象。

下面是演示 C# 中 Builder 模式的简单示例:

public class Car

{

public string Make { get; set; }

public string Model { get; set; }

public int Year { get; set; }

public string Color { get; set; }

public Car(string make, string model, int year, string color)

{

Make = make;

Model = model;

Year = year;

Color = color;

}

public override string ToString()

{

return $"Make: {Make}, Model: {Model}, Year: {Year}, Color: {Color}";

}

}

public class CarBuilder

{

private string make;

private string model;

private int year;

private string color;

public CarBuilder SetMake(string make)

{

this.make = make;

return this;

}

public CarBuilder SetModel(string model)

{

this.model = model;

return this;

}

public CarBuilder SetYear(int year)

{

this.year = year;

return this;

}

public CarBuilder SetColor(string color)

{

this.color = color;

return this;

}

public Car Build()

{

return new Car(make, model, year, color);

}

}

在此示例中,该类表示我们要生成的复杂对象。该类提供用于设置对象属性的方法。该方法使用类中的方法设置的属性创建最终对象。该类在每次方法调用后返回,允许方法链接,使生成对象的过程更加直观和可读。

通过这种方式,Builder 设计模式通过将构造过程与对象的最终表示分离,提供了一种创建复杂对象的灵活方法。

原型模式

原型模式是一种创建设计模式,允许您通过克隆现有对象来创建对象,而不是直接创建新实例。当创建大量类似对象既耗时又耗费资源时,则使用此模式。原型模式提供了一种创建类似对象的有效方法,而不必每次都经历对象创建的整个过程。

使用原型模式的主要好处之一是,它允许您创建新对象,而无需经历对象创建的整个过程。这减少了创建新对象所需的时间和资源,并可以更轻松地快速创建类似的对象。

原型模式可以使用浅克隆或深克隆机制来实现。浅层克隆会创建一个与原始对象具有相同属性的新对象,但不会克隆这些属性本身。另一方面,深度克隆会创建一个与原始对象具有相同属性的新对象,并且还会克隆属性本身。

public abstract class Prototype

{

public int X { get; set; }

public int Y { get; set; }

public Prototype(int x, int y)

{

X = x;

Y = y;

}

public abstract Prototype Clone();

}

public class ConcretePrototype : Prototype

{

public ConcretePrototype(int x, int y) : base(x, y) { }

public override Prototype Clone()

{

return (Prototype)this.MemberwiseClone();

}

}

在上面的示例中,抽象 Prototype 类定义了 Clone() 方法,该方法用于克隆对象。ConcretePrototype 类实现 Clone() 方法,使用 MemberwiseClone 方法创建对象的浅克隆。

若要使用 Prototype 模式,首先要创建 ConcretePrototype 类的实例。然后,使用 Clone() 方法基于原始对象创建新对象。每次使用 Clone() 方法时,都会创建一个具有与原始对象相同属性的新对象。

相关阅读