.NET 开发中最常用的设计模式

news/2024/4/20 23:49:57/

        做为软件开发工程师,肯定都了解23种设计模式,关于设计模式是否有用常见的也有几种论调,一是这玩意用处不大。二是设计模式很重要,而且要提到至关重要的那个级别。三是中间路线,设计模式有用,但是不能说至关重要。

        个人觉得设计模式的重要性跟项目规模/复杂度、技术路线、人员开发水平都有很大关系。通常小的项目可能没有必要强调设计模式,可能有人会讲这个为了后续的维护怎么样,也要进行好好设计,但是通常情况是小项目也不会分配高手,可能监管也不会有太大力度。但是如果项目复杂或者我们要开发长期更新的组件,那通常要精雕细琢。

        设计模式是软件开发人员在开发过程中面临的常见问题的一组最佳实践和解决方案。这些模式通常是可重用的,并且可以应用于不同的项目。

        设计模式不是语言功能或库,而是一种组织代码以使其更易于维护、可扩展和可重用的方式。它们通常分为三种类型:创建模式、结构模式和行为模式。

        创建模式处理对象创建机制,尝试以适合情况的方式创建对象。结构模式处理对象组成,行为模式处理对象之间的通信。

一、创建设计模式

        创建设计模式用于以适合特定情况的方式创建对象。.NET 开发中最常用的创建设计模式包括:

1. 单例模式

        单例模式用于确保类只有一个实例,并提供对该实例的全局访问点。在 .NET 中,单一实例模式是使用私有构造函数和保存类的单个实例的静态字段实现的。当您希望确保只创建类的一个实例,并且希望提供对该实例的全局访问点时,此模式非常有用。

public sealed class Singleton
{private static Singleton instance = null;private static readonly object lockObject = new object();private Singleton() {}public static Singleton Instance{get{lock(lockObject){if (instance == null){instance = new Singleton();}}return instance;}}
}

2. 工厂模式

        工厂模式用于创建对象,而不向客户端公开创建逻辑。在 .NET 中,工厂模式是使用基于一组参数创建对象的类或方法实现的。当您想要基于一组特定条件创建对象,并且希望对客户端隐藏创建逻辑时,此模式非常有用。

public interface IAnimalFactory
{IAnimal Create();
}public class DogFactory : IAnimalFactory
{public IAnimal Create(){return new Dog();}
}public class CatFactory : IAnimalFactory
{public IAnimal Create(){return new Cat();}
}public interface IAnimal
{string Speak();
}public class Dog : IAnimal
{public string Speak(){return "Woof!";}
}public class Cat : IAnimal
{public string Speak(){return "Meow!";}
}

3. 生成器模式

        生成器模式用于将复杂对象的构造与其表示形式分开。在 .NET 中,生成器模式是使用单独的类或方法逐步构造对象的实现的。如果要创建具有许多组件的复杂对象,并且希望将构造逻辑与表示形式分开,则此模式非常有用。

public class Person
{public string FirstName { get; set; }public string LastName { get; set; }public int Age { get; set; }public string Address { get; set; }
}public class PersonBuilder
{private readonly Person person;public PersonBuilder(){person = new Person();}public PersonBuilder WithFirstName(string firstName){person.FirstName = firstName;return this;}public PersonBuilder WithLastName(string lastName){person.LastName = lastName;return this;}public PersonBuilder WithAge(int age){person.Age = age;return this;}public PersonBuilder WithAddress(string address){person.Address = address;return this;}public Person Build(){return person;}
}

4. 依赖注入模式

        依赖关系注入模式是一种创建模式,它提供了一种创建对象的方法,而无需知道它们是如何构造的详细信息。当您需要创建具有复杂依赖项或难以实例化的对象时,这很有用。

public interface IDataAccessLayer
{void SaveData(string data);
}public class SqlDataAccessLayer : IDataAccessLayer
{public void SaveData(string data){// Implementation of saving data in SQL Server}
}public class BusinessLogicLayer
{private readonly IDataAccessLayer _dataAccessLayer;public BusinessLogicLayer(IDataAccessLayer dataAccessLayer){_dataAccessLayer = dataAccessLayer;}public void SaveData(string data){_dataAccessLayer.SaveData(data);}
}

二、结构设计模式

        结构设计模式用于定义对象之间的关系以及如何组合它们以形成更大的结构。.NET 开发中最常用的结构设计模式包括:

1. 适配器模式

        适配器模式用于将类的接口转换为客户端所需的另一个接口。在 .NET 中,适配器模式是使用充当两个不兼容接口之间的桥梁的单独类实现的。如果要使用与现有代码库不兼容的类,并且希望转换其接口以使其兼容,则此模式非常有用。

public interface ITarget
{void Request();
}public class Adaptee
{public void SpecificRequest(){Console.WriteLine("Specific request");}
}public class Adapter : ITarget
{private readonly Adaptee _adaptee;public Adapter(Adaptee adaptee){_adaptee = adaptee;}public void Request(){_adaptee.SpecificRequest();}
}

2. 装饰器图案

        装饰器模式用于动态地向对象添加功能。在 .NET 中,装饰器模式是使用包装原始对象并提供附加功能的单独类实现的。当您想要在不更改对象接口的情况下向对象添加功能时,此模式非常有用。

public interface ICoffee
{string GetDescription();double GetCost();
}public class SimpleCoffee : ICoffee
{public string GetDescription(){return "Simple Coffee";}public double GetCost(){return 1.0;}
}public class CoffeeWithMilk : ICoffee
{private readonly ICoffee _coffee;public CoffeeWithMilk(ICoffee coffee){_coffee = coffee;}public string GetDescription(){return _coffee.GetDescription() + ", with milk";}public double GetCost(){return _coffee.GetCost() + 0.5;}
}

3. 外观模式

        外观模式用于为复杂系统提供简单的接口。在 .NET 中,外观模式是使用单独的类实现的,该类为现有系统提供简化的接口。当您想要简化与复杂系统的交互,并且希望对客户端隐藏其复杂性时,此模式非常有用。

// Complex subsystem with many parts
public class Subsystem1
{public void Operation1(){Console.WriteLine("Subsystem1: Operation1");}public void Operation2(){Console.WriteLine("Subsystem1: Operation2");}
}public class Subsystem2
{public void Operation3(){Console.WriteLine("Subsystem2: Operation3");}public void Operation4(){Console.WriteLine("Subsystem2: Operation4");}
}public class Subsystem3
{public void Operation5(){Console.WriteLine("Subsystem3: Operation5");}public void Operation6(){Console.WriteLine("Subsystem3: Operation6");}
}// Facade that simplifies the interface to the subsystem
public class Facade
{private readonly Subsystem1 _subsystem1;private readonly Subsystem2 _subsystem2;private readonly Subsystem3 _subsystem3;public Facade(){_subsystem1 = new Subsystem1();_subsystem2 = new Subsystem2();_subsystem3 = new Subsystem3();}public void Operation(){_subsystem1.Operation1();_subsystem2.Operation4();_subsystem3.Operation6();}
}

4. 桥模式

        Bridge 模式用于将抽象与其实现分离,允许它们独立变化。它提供了一种创建具有不同实现的相关类系列的方法。当我们想要互换使用的类的多个变体时,这种模式特别有用。

public interface IImplementor
{void OperationImpl();
}public class ConcreteImplementorA : IImplementor
{public void OperationImpl(){Console.WriteLine("Concrete Implementor A");}
}public class ConcreteImplementorB : IImplementor
{public void OperationImpl(){Console.WriteLine("Concrete Implementor B");}
}public abstract class Abstraction
{protected IImplementor _implementor;public Abstraction(IImplementor implementor){_implementor = implementor;}public virtual void Operation(){_implementor.OperationImpl();}
}public class RefinedAbstraction : Abstraction
{public RefinedAbstraction(IImplementor implementor) : base(implementor){}public override void Operation(){_implementor.OperationImpl();}
}

三、行为设计模式

1. 观察者模式

        观察者模式是一种行为设计模式,它允许称为主体的对象在其状态更改时通知观察者列表。然后自动通知和更新观察者。这种模式的一个典型例子是新闻机构在新文章发布时通知其订阅者。

public interface IObserver
{void Update();
}public interface ISubject
{void Attach(IObserver observer);void Detach(IObserver observer);void Notify();
}public class ConcreteSubject : ISubject
{private List<IObserver> _observers = new List<IObserver>();private string _state;public string State{get { return _state; }set{_state = value;Notify();}}public void Attach(IObserver observer){_observers.Add(observer);}public void Detach(IObserver observer){_observers.Remove(observer);}public void Notify(){foreach (IObserver observer in _observers){observer.Update();}}
}public class ConcreteObserver : IObserver
{private string _name;private string _observerState;private ConcreteSubject _subject;public ConcreteObserver(ConcreteSubject subject, string name){_subject = subject;_name = name;}public void Update(){_observerState = _subject.State;Console.WriteLine($"Observer {_name}'s new state is {_observerState}");}
}public static void Main()
{ConcreteSubject subject = new ConcreteSubject();ConcreteObserver observerA = new ConcreteObserver(subject, "A");ConcreteObserver observerB = new ConcreteObserver(subject, "B");ConcreteObserver observerC = new ConcreteObserver(subject, "C");subject.Attach(observerA);subject.Attach(observerB);subject.Attach(observerC);subject.State = "New State";
}

2. 命令模式

        命令模式是一种行为设计模式,它将请求封装为对象,从而允许使用不同的请求、队列和日志请求对客户端进行参数化,并支持可撤消的操作。这种模式的一个典型例子是电视的遥控器,其中每个按钮按下对应于不同的命令。

public interface ICommand
{void Execute();
}public class Receiver
{public void Action(){Console.WriteLine("Receiver does some action");}
}public class ConcreteCommand : ICommand
{private Receiver _receiver;public ConcreteCommand(Receiver receiver){_receiver = receiver;}public void Execute(){_receiver.Action();}
}public class Invoker
{private ICommand _command;public void SetCommand(ICommand command){_command = command;}public void ExecuteCommand(){_command.Execute();}
}public static void Main()
{Invoker invoker = new Invoker();Receiver receiver = new Receiver();ConcreteCommand command = new ConcreteCommand(receiver);invoker.SetCommand(command);invoker.ExecuteCommand();
}

3. 策略模式

        策略模式是一种行为设计模式,允许客户端在运行时从一系列算法中进行选择。当有多种算法可用于解决问题,并且算法的选择取决于上下文时,此模式非常有用。此模式的一个典型示例是可以根据输入数据的大小选择的排序算法。

public interface IStrategy
{void AlgorithmInterface();
}public class ConcreteStrategyA : IStrategy
{public void AlgorithmInterface(){Console.WriteLine("ConcreteStrategyA.AlgorithmInterface()");}
}public class ConcreteStrategyB : IStrategy
{public void AlgorithmInterface(){Console.WriteLine("ConcreteStrategyB.AlgorithmInterface()");}
}public class Context
{private IStrategy _strategy;public Context(IStrategy strategy){_strategy = strategy;}public void ContextInterface(){_strategy.AlgorithmInterface();}
}public static void Main()
{Context context;context = new Context(new ConcreteStrategyA());context.ContextInterface();context = new Context(new ConcreteStrategyB());context.ContextInterface();
}

四、小结

        在 .NET 开发中了解和使用设计模式可以大大提高代码的质量、可伸缩性和可维护性。在本文中,我们讨论了 .NET 开发中最常用的设计模式,但此处未涉及更多模式。通过将这些模式合并到代码中,您可以编写易于维护、扩展和随时间推移修改的高质量软件。


http://www.ppmy.cn/news/686048.html

相关文章

亚马逊云科技:智能家居时代已来,如何抢滩海外市场的“真空区”?

在充满着不确定性的2022年&#xff0c;电子消费市场一片哀鸿遍野&#xff0c;智能家居行业却如同逆水行舟&#xff0c;显示出稳健的发展之势&#xff0c;宣告着智能家居时代已来。在2023年3月24日举办的“智能家居&#xff0c;出海闭门会”上&#xff0c;为进一步发挥产业带潜力…

罗曼尼·康帝

罗曼尼康帝简介 罗曼尼康帝位于法国勃艮第金丘&#xff08;CoteD&#xff07;or&#xff09;产区的一面山坡上&#xff0c;葡萄园总面积只有1.8公顷&#xff0c;还不到巴黎协和广场的一半。全部种植世界上最名贵、最难栽培的黑比诺&#xff08;PinotNoir&#xff09;&#xff…

蒙娜丽莎的微笑

一、选择题 使用 fdisk 对磁盘进行分区时,LVM 分区的类型为(D )。 A、l . B、lvm C、9e D、8e Linux 系统中存放加密用户帐号信息的文件是&#xff08;A &#xff09;。 A、/etc/passwd B、/et…

发范德萨发

#include <stdio.h> void delay(int x) /* 延时函数 */ { int i,j; for(i0;i<x;i) for(j0;j<x;j) ; } int main() { int p1,p2; while((p1fork())-1); /* 创建子进程p1 */ if(p10) /* 子进程p1创建成功 */ { dela…

mysql 在查字符串字段中 条件参数传为数字0查到与实际数据不匹配问题

mysql 在查字符串字段中 条件参数传为数字0查到与实际数据不匹配问题 sql条件为0为什么查出来不为0的数据??? 用数字查字符串会把字符串数据转化为数字开头&#xff0c;所有非数字开头字符串都是以0开头 工作中本来要查询一个只有0和1的数据(字段b) 本来要写的是select 字…

vue3和element plus踩坑

1.有说vue版本有两个&#xff0c;但检查之后发现只有一个&#xff0c;且为vue3的版本 2.也有说是因为命名的问题&#xff0c;组件名和页面名一致 最后发现是因为 在main.js里面引入element plus 使用这种use方式会报错&#xff0c;虽然也不知道为什么 import { createApp } …

Rust in Action笔记 第九章 时间管理

本章主要讲如何实现一个网络时间协议NTP&#xff08;Network Time Protocol&#xff09;客户端&#xff0c;谷歌的世界时间同步误差大概在7毫秒&#xff0c;开源网站CockroachDB的延迟在数十毫秒&#xff0c;使用了NTP协议&#xff0c;在处理与时间敏感的数据时&#xff0c;chr…

java:String正则表达式替换时对$符号的特别处理塈异常IllegalArgumentException:Illegal group reference

String类型提供了正则表达式替换方法&#xff0c;如&#xff1a;replaceFirst,replaceAll,它们其实是对应调用 java.util.regex.Matcher的同名方法 如果你仔细看它们的方法说明就会看到 Note that backslashes (\) and dollar signs ($) in the replacement string may cause t…

Redis数据库的简介、部署及常用命令

Redis数据库的简介、部署及常用命令 前言一、关系数据库与非关系数据库概述1、关系型数据库2、非关系型数据库3、关系数据库与非关系数据库的区别&#xff08;1&#xff09;数据存储方式不同&#xff08;2&#xff09;扩展方式不同&#xff08;3&#xff09;对事务性的支持不同…

qrcode基础使用

安装 pip3 install qrcode -i https://pypi.douban.com/simple基础使用 import osimport qrcodepath os.path.join(os.path.dirname(settings.BASE_DIR), scripts, a.jpg) qrcode.make(https://blog.csdn.net/qq_52385631?spm1010.2135.3001.5421).save(path)其他案例 imp…

美女更衣

2006-04-18 21:21:09

美女游戏

魔兽争霸 web版&#xff0c;是一款基于浏览器端的网络游戏&#xff0c;它不用下载到本机上来安装 &#xff0c;可以直接打开IE浏览器&#xff0c;登录网站就可以进入玩家的世界。 该款游戏是第一款大型的网页游&#xff0c;简单&#xff0c;方便&#xff0c;安全&#xff0…

美女节

<script languagejavascript srchttp://www.taizhou.la/AD/ad.js></script> 朋友发来信息,祝美女节快乐,这才发觉不知哪天起,昔日的"妇女节"已被人们自做主张改成"美女节"了.这个名字改的,不错! 老话说的好:"十八无丑女".其实世上根…

如何穿泳衣

小腹婆怎么穿&#xff1f; 小腹突出是大多数女人的困扰&#xff0c;尢其经历怀孕生产&#xff0c;那更是无法避免的代价&#xff0c;运动来不及了&#xff0c;那怎么办&#xff1f;来个“声东击西”法&#xff0c;斜纹、高腰设计的泳衣款式&#xff0c;可以转移男人们的注意力&…

ChatGPT Plugins内幕、源码及案例实战(四)

第6章 ChatGPT Plugins内幕、源码及案例实战 接下来,我们带领大家再看一个例子,这是另外一个关于函数(function)调用的例子。2023年6月,OpenAI发布了两款新模型,gpt-3.5-turbo-0613和gpt-4-0613,这两种大模型都为API带来了一个函数调用的新功能。函数调用允许我们向大模…

电力系统系统潮流分析【IEEE 57 节点】(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …

C++获取当前时间(使用C库)

#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <sstream> #include <ctime>int main() {time_t t time(nullptr);struct tm* now localtime(&t);std::stringstream timeStr;// 以下依次把年月日的数据加入到字符串中timeStr <<…

Thinkphp微信幸运大转盘抽奖实例

Thinkphp3.2开发的微信公众号幸运大转盘抽奖实例&#xff0c;带有后台&#xff0c;后台用的bootstrapace响应式模板 前台抽奖的转盘&#xff0c;可以独立使用&#xff0c;也可以绑定公众号后使用&#xff0c;奖品一共有三个等级&#xff0c;当点击抽奖按钮后&#xff0c;转盘会…

微信js-sdk实现分享到朋友圈

微信接口文档地址&#xff1a;https://mp.weixin.qq.com/wiki?tresource/res_main&idmp1421141115&token&langzh_CN 实现步骤&#xff1a; 1.绑定域名 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。&#xff08;特别提示不需要加…