C# 和 .NET 开发的 10 种基本模式
xsobi 2025-01-05 20:44 1 浏览
概述:设计模式是软件设计中出现的常见问题的可重用解决方案。它们是用于解决设计问题的模板,这些设计问题已被证明在各种情况下都是有效的。它们为开发人员提供了通用词汇和对最佳实践的共同理解,使他们更容易就复杂的设计问题进行沟通和协作。总而言之,它们很重要,因为它们:为常见设计问题提供经过验证的解决方案促进开发人员之间的共同词汇和共识节省创建解决方案的时间和精力推广模块化和可维护的代码库适用于各种设计问题,不受平台或语言限制。设计模式并不特定于任何编程语言或技术。它们适用于任何软件开发项目,无论使用何种平台或语言。单例模式单一实例模式是一种设计模式,它将类限制为只有一个实例,同时提供对此实例的全局访问点。当
设计模式是软件设计中出现的常见问题的可重用解决方案。它们是用于解决设计问题的模板,这些设计问题已被证明在各种情况下都是有效的。它们为开发人员提供了通用词汇和对最佳实践的共同理解,使他们更容易就复杂的设计问题进行沟通和协作。
总而言之,它们很重要,因为它们:
- 为常见设计问题提供经过验证的解决方案
- 促进开发人员之间的共同词汇和共识
- 节省创建解决方案的时间和精力
- 推广模块化和可维护的代码库
- 适用于各种设计问题,不受平台或语言限制。
设计模式并不特定于任何编程语言或技术。它们适用于任何软件开发项目,无论使用何种平台或语言。
单例模式
单一实例模式是一种设计模式,它将类限制为只有一个实例,同时提供对此实例的全局访问点。当只需要一个类的单个实例来控制整个执行过程中的操作时,将使用此模式。当您需要确保只创建类的一个实例并且可以从应用程序中的单个点访问该实例时,它特别有用。
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;
}
}
}
在此示例中,该属性使用双重检查的锁定机制来确保只创建类的一个实例,即使在多线程环境中也是如此。InstanceSingleton
工厂模式
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;
}
}
}
在此示例中,该类提供了一种用于创建类型为 的对象的方法。该方法接受一个参数,该参数确定要创建的形状类型,并返回相应的对象。ShapeFactoryIShapeGetShapeshapeType
装饰器图案
装饰器模式是一种结构设计模式,允许您在不更改其底层结构的情况下动态添加或扩展对象的行为。它为扩展对象的功能提供了一种灵活的替代方法。
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(#34;{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 { }
在上面的例子中,我们有两个混凝土工厂,和 ,它们实现了接口。这些工厂分别提供了创建与汽车和卡车相关的对象的方法。通过使用抽象工厂,我们可以创建一整套相关对象,例如车身、汽车底盘、车窗、卡车车身、卡车底盘和卡车车窗,而无需指定要实例化的确切类。CarFactoryTruckFactoryAbstractVehicleFactory
当我们需要创建一组属于同一系列且结构相似但实现细节不同的对象时,抽象工厂模式会很有用。通过使用抽象工厂,我们可以封装对象的创建,并使我们的代码更加灵活和可维护。
生成器模式
构建器设计模式是一种创建设计模式,它提供了一种以增量方式构建复杂对象的方法。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 #34;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);
}
}
在此示例中,该类表示我们要生成的复杂对象。该类提供用于设置对象属性的方法。该方法使用类中的方法设置的属性创建最终对象。该类在每次方法调用后返回,允许方法链接,使生成对象的过程更加直观和可读。CarCarBuilderCarBuildCarCarBuilderCarBuilderthisCar
通过这种方式,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() 方法时,都会创建一个具有与原始对象相同属性的新对象。
相关推荐
- 什么是 XML 站点地图?为什么要有它?
-
一份好的XML站点地图可以作为您网站的路线图,引导Google找到您所有的重要页面。XML站点地图对SEO非常有利,即使您的内部链接不完美,Google也能快速找到您的重要页面。这篇文...
- springboot整合mybatis使用xml实现sql语句的查询配置
-
首先肯定还是引入mybatis依赖<!--https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-b...
- IDEA 这么设置 Maven,再也不用担心依赖下载失败了
-
Hello,大家好,我是楼下小黑哥。B站视频版本...
- WordPress网站被利用xmlrpc.php攻击解决办法
-
最近看了百度云加速后台的数据报表,发现有很多针对WordPress的攻击,其实就是利用xmlrpc.php文件来攻击。虽然目前站点一切安好,但是据说如果不采取相应措施解决的话,很有可能会被这些攻击导致...
- 看大佬对Maven讲解有多深,Maven setting.xml文件 了解一下
-
通常我们安装了Maven之后会对Mavensetting.xml(Maven的配置文件做一些自定义),本章我们将详细地学习一下Mavensetting.xml文件。文件位置一般存在与Maven安装...
- XML文档篇(二):认识 xsd 文档
-
前面介绍了基于XML的DTD,详见:XML文档篇:认识DTD(一)。今天再来分享一个它的替代者,...
- Mybatis 中xml和注解映射,分分钟搞定
-
MyBatis提供了XML配置和注解配置两种方式。今天就来搞搞这两种方式是如何实现的。...
- 您的网站需要XML站点地图吗?
-
昨天有人咨询我们:“向百度提交网站地图有多重要?”首先,让我们了解一下“XML网站地图有多重要?”您是否需要XML网站地图?...
- 详细解释Xml中的Schema约束(保姆级)
-
我本人总是爱忘记这个约束,说实话不是太难,因此想写这篇文章详细记录下,希望对有同样需要的小伙伴能够提供帮助。Xml约束主要有两种:dtd约束(比较简单)schema约束(常用、复杂)dtd约束比较简单...
- HTML和xml有哪些区别?
-
HTML和XML都是用于描述和组织数据的标记语言,但它们之间有着许多区别。本文将详细介绍HTML和XML的区别,包括语法、标记、应用场景等方面。一、语法差异...
- 开源XML数据库 BaseX
-
BaseX是一个开源的XML数据库系统,包括一个前端用户操作管理界面XQueryEditor。提供高效的XPath和XQuery处理,包含了对W3CUpdate和FullText扩展的全...
- 一篇文章让你弄清楚XML文件的规范与使用
-
可扩展标记语言(ExtensibleMarkupLanguage,简称XML)是一种标记语言。所谓的标记是指计算机所能理解的信息符号,通过标记可以实现软件开发者与计算机之间的信息沟通。我们常见的H...
- Python 3 实现在线xml sitemap索引文件提取URL到指定文件
-
毫无疑问,在SEO分析网站结构和开放搜索引擎端抓取页面数时,对sitemap文件的分析是最好的入手点。通常规模不是太小的网站URL数量都会超过5万条,而搜索引擎要求单个sitemap文件的数量不能超过...
- 从零开始学Java之带你学会解析XML文件
-
一.XML简介1.概念XML(ExtensibleMarkupLanguage,可扩展的标记语言),作为一种标记语言,它是标准通用标记语言的子集。XML给我们提供了可扩展性和自定义标签的特性...
- 解除 网课失去焦点/离开页面 就自动暂停 的限制
-
用代码解决实际生活中的问题h5如果视频是video元素,可以写个定时器,每秒钟设置一下播放状态...
- 一周热门
- 最近发表
- 标签列表
-
- grid 设置 (58)
- 移位运算 (48)
- not specified (45)
- patch补丁 (31)
- 导航栏 (58)
- context xml (46)
- scroll (43)
- dedecms模版 (53)
- c 视频教程下载 (33)
- listview排序 (33)
- firebug 使用 (31)
- characterencodingfilter (33)
- getmonth (34)
- hibernate教程 (31)
- label换行 (33)
- curlpost (31)
- android studio 3 0 (34)
- android应用开发 (31)
- html转js (35)
- 索引的作用 (33)
- css3 0 (31)
- checkedlistbox (34)
- localhost 8080 (32)
- 多态 (32)
- xmlhttp (35)