.net core 中的经典设计模式的应用

.net core 中的经典设计模式的应用

Intro

前段时间我们介绍了23种设计模式,今天来分享一下 .net core 源码中我觉得比较典型的设计模式的应用

实例

责任链模式

asp.net core 中间件的设计就是责任链模式的应用和变形,

每个中间件根据需要处理请求,并且可以根据请求信息自己决定是否传递给下一个中间件,我也受此启发,封装了一个 PipelineBuilder 可以轻松构建中间件模式代码,可以参考这篇文章 https://www.cnblogs.com/weihanli/p/12700006.html

中间件示例:

app.UseStaticFiles();app.UseResponseCaching();
app.UseResponseCompression();app.UseRouting();app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());app.UseAuthentication();
app.UseAuthorization();app.UseEndpoints(endpoints =>
{endpoints.MapControllers();endpoints.MapControllerRoute(name: "areaRoute", "{area:exists}/{controller=Home}/{action=Index}");endpoints.MapDefaultControllerRoute();
});

PipelineBuilder 实际示例:

var requestContext = new RequestContext()
{RequesterName = "Kangkang",Hour = 12,
};var builder = PipelineBuilder.Create<RequestContext>(context =>{Console.WriteLine($"{context.RequesterName} {context.Hour}h apply failed");}).Use((context, next) =>{if (context.Hour <= 2){Console.WriteLine("pass 1");}else{next();}}).Use((context, next) =>{if (context.Hour <= 4){Console.WriteLine("pass 2");}else{next();}}).Use((context, next) =>{if (context.Hour <= 6){Console.WriteLine("pass 3");}else{next();}});
var requestPipeline = builder.Build();
foreach (var i in Enumerable.Range(1, 8))
{Console.WriteLine();Console.WriteLine($"--------- h:{i} apply Pipeline------------------");requestContext.Hour = i;requestPipeline.Invoke(requestContext);Console.WriteLine("----------------------------");Console.WriteLine();
}

建造者模式

asp.net core 中的各种 BuilderHostBuilder/ConfigurationBuilder 等,这些 Builder 大多既是 Builder 又是 Director,Builder 本身知道如何构建最终的 Product(Host/Configuration)

var host = new HostBuilder().ConfigureAppConfiguration(builder =>{// 注册配置builder.AddInMemoryCollection(new Dictionary<string, string>(){{"UserName", "Alice"}}).AddJsonFile("appsettings.json");}).ConfigureServices((context, services) =>{// 注册自定义服务services.AddSingleton<IIdGenerator, GuidIdGenerator>();services.AddTransient<IService, Service>();if (context.Configuration.GetAppSetting<bool>("XxxEnabled")){services.AddSingleton<IUserIdProvider, EnvironmentUserIdProvider>();}}).Build();

工厂模式

依赖注入框架中有着大量的工厂模式的代码,注册服务的时候我们可以通过一个工厂方法委托来获取服务实例,

依赖注入的本质就是将对象的创建交给 IOC 容器来处理,所以其实 IOC 容器本质就是一个工厂,从 IOC 中获取服务实例的过程就是工厂创建对象的过程,只是会根据服务的生命周期来决定是创建新对象还是返回已有对象。

services.AddSingleton(sp => new Svc2(sp.GetRequiredService<ISvc1>(), "xx"));

单例模式

在 dotnet 中有一个 TimeQueue 的类型,纯正的饿汉模式的单例模式代码

class TimerQueue
{#region singleton pattern implementation// The one-and-only TimerQueue for the AppDomain.static TimerQueue s_queue = new TimerQueue();public static TimerQueue Instance{get { return s_queue; }}private TimerQueue(){// empty private constructor to ensure we remain a singleton.}#endregion// ...
}

https://referencesource.microsoft.com/#mscorlib/system/threading/timer.cs,49

在 dotnet 源码中还有一些懒汉式的单例模式

使用 Interlocked 原子操作

internal class SimpleEventTypes<T>: TraceLoggingEventTypes
{private static SimpleEventTypes<T> instance;internal readonly TraceLoggingTypeInfo<T> typeInfo;private SimpleEventTypes(TraceLoggingTypeInfo<T> typeInfo): base(typeInfo.Name,typeInfo.Tags,new TraceLoggingTypeInfo[] { typeInfo }){this.typeInfo = typeInfo;}public static SimpleEventTypes<T> Instance{get { return instance ?? InitInstance(); }}private static SimpleEventTypes<T> InitInstance(){var newInstance = new SimpleEventTypes<T>(TraceLoggingTypeInfo<T>.Instance);Interlocked.CompareExchange(ref instance, newInstance, null);return instance;}
}

另外一个示例,需要注意,下面这种方式不能严格的保证只会产生一个实例,在并发较高的情况下可能不是同一个实例,这也可以算是工厂模式的一个示例

static internal class ConfigurationManagerHelperFactory 
{private const string ConfigurationManagerHelperTypeString = "System.Configuration.Internal.ConfigurationManagerHelper, " + AssemblyRef.System;static private volatile IConfigurationManagerHelper s_instance;static internal IConfigurationManagerHelper Instance {get {if (s_instance == null) {s_instance = CreateConfigurationManagerHelper();}return s_instance;}}[ReflectionPermission(SecurityAction.Assert, Flags = ReflectionPermissionFlag.MemberAccess)][SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Justification = "Hard-coded to create an instance of a specific type.")]private static IConfigurationManagerHelper CreateConfigurationManagerHelper() {return TypeUtil.CreateInstance<IConfigurationManagerHelper>(ConfigurationManagerHelperTypeString);}
}

原型模式

dotnet 中有两个数据结构 Stack/Queue 这两个数据都实现了 ICloneable 接口,内部实现了深复制 来看 StackClone 方法实现:

public virtual Object Clone()
{Contract.Ensures(Contract.Result<Object>() != null);Stack s = new Stack(_size);s._size = _size;Array.Copy(_array, 0, s._array, 0, _size);s._version = _version;return s;
}

详细可以参考:https://referencesource.microsoft.com/#mscorlib/system/collections/stack.cs,6acda10c5f8b128e

享元模式

string intern(字符串池),以及 Array.Empty<int>()/Array.Empty<string>()

策略模式

asp.net core 中的认证和授权,我觉得就是策略模式的应用,在使用 [Authorize] 的时候会使用默认的 policy,也可以指定要使用的策略 [Authorize("Policy1")] 这样就会使用另外一种策略 Policy1,policy 还是比较简单的

policy 是用来根据用户的认证信息来控制授权访问的,而认证则是根据当前上下文(请求上下文、线程上下文、环境上下文等)的信息进行认证从而获取用户信息的过程

而不同的认证模式(Cookie/JWT/自定义Token等)其实是不同的处理方法,也就是策略模式中不同的算法实现,指定哪种认证模式,就是使用哪种算法实现来获取用户信息

观察者模式

常使用事件(event)进行解耦,外部代码通过订阅事件来解耦,实现对内部状态的观察

Process 类中有很多事件,可以用来捕获另一个进程中的输出,错误等

public event DataReceivedEventHandler OutputDataReceived;public event DataReceivedEventHandler ErrorDataReceived;

通常这两个事件我们就可以获取到另外一个进程中的输出信息,除此之外还有很多的类在使用事件,相信你也用过很多

组合模式

WPF、WinForm 中都有控件的概念,这些控件的设计属于是组合模式的应用,所有的控件都会继承于某一个共同的基类, 使得单个对象和组合对象都可以看作是他们共同的基类对象

迭代器模式

c# 中定义了迭代器模式,原始定义:

// 聚集抽象
public interface IEnumerable
{/// <summary>Returns an enumerator that iterates through a collection.</summary>/// <returns>An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.</returns>IEnumerator GetEnumerator();
}// 迭代器抽象
public interface IEnumerator
{/// <summary>Advances the enumerator to the next element of the collection.</summary>/// <returns>/// <see langword="true" /> if the enumerator was successfully advanced to the next element; <see langword="false" /> if the enumerator has passed the end of the collection.</returns>/// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created.</exception>bool MoveNext();/// <summary>Gets the element in the collection at the current position of the enumerator.</summary>/// <returns>The element in the collection at the current position of the enumerator.</returns>object Current { get; }/// <summary>Sets the enumerator to its initial position, which is before the first element in the collection.</summary>/// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created.</exception>void Reset();
}

Array 和 List 各自实现了自己的迭代器,感兴趣可以去看下源码

More

.net core 中的设计模式应用还有很多,不仅上面提到的这几个模式,也不仅仅是我所提到的这几个地方

上面有一些示例是直接用的 dotnet framework 中的源码,因为有很多代码都是类似的,用的 https://referencesource.microsoft.com 的源码

以上均是个人理解,如果有错误还望指出,十分感谢,欢迎补充更多设计模式应用的源码实例

Reference

  • https://github.com/dotnet/aspnetcore

  • https://github.com/dotnet/extensions

  • https://github.com/dotnet/corefx

  • https://github.com/dotnet/aspnetcore

  • https://github.com/dotnet/runtime

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/308110.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8种方法解决vue创建项目报错:command failed: npm install --loglevel error

8种方法解决vue项目创建失败问题1、重建项目2、清除缓存3、重装淘宝源4、修改useTaobaoRegistry5、重装node6、删除npmrc文件7、 node版本问题8、css编辑工具选择9、管理员身份运行踩了这个巨大的坑&#xff01;&#xff01; 试了一个晚上终于找到了创建项目成功了T_T 当报错了…

40. 组合总和 II021(回溯法)

一&#xff1a;题目 给定一个数组 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用一次。 注意&#xff1a;解集不能包含重复的组合。 示例 1:输入: candidates [10,1,2,…

.NET Core + Kubernetes:Helm

Helm[1] 作为 Kubernetes 体系的包管理工具&#xff0c;已经逐渐成为了应用分发标准&#xff0c;在 .NET 开发中&#xff0c;可以理解为与 NuGet 包类似。回顾之前文章中的介绍&#xff0c;Kubernetes 中单个服务的部署有时会涉及到多种资源类型&#xff0c;如&#xff1a;Depl…

vue项目中引入阿里图标iconfont

vue如何在创建好的项目中引入阿里图标iconfont呢&#xff0c;涉及到以下几个步骤&#xff1a; 1、首先先到阿里图标官方网站https://www.iconfont.cn/&#xff0c;先对账户进行登录&#xff0c;登录完成后任意选择几个图标加入购物车 2、加入购物车后&#xff0c;点击页面最右…

78. 子集022(回溯法)

一&#xff1a;题目 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;…

.NET core3.1使用cookie进行身份认证

一个系统&#xff0c;用户身份认证少不了&#xff0c;ASP.NET Core提供完整的解决方案Identity&#xff0c;用户创建和维护登录名&#xff1b;也提供能cookie和JwtBearer认证方案&#xff0c;当然你可以使用第三方认证Oauth、openId。项目没有采用前后端分离&#xff0c;是一个…

vue项目中使用vue-router进行路由配置及嵌套多级路由

在vue项目中&#xff0c;很多时候我们需要二级路由或者三级路由来跳转页面&#xff0c;但大部分需求下我们都只用到了二级路由&#xff0c;有小伙伴就会发现&#xff0c;用到三级路由的时候&#xff0c;就会突然不知所措&#xff0c;是有新的方法呢&#xff0c;还是跟二级路由配…

解决流氓软件方法(亲测有效)

一:问题描述 本来我想在百度上下载一个API文档&#xff0c;我当然知道是取官网上下载了&#xff0c;但是我想要的是中文版&#xff0c;所以我就搜啊搜&#xff0c;搜到脚本之家 &#xff0c;那里面可以下载&#xff0c;我记得以前在里面下载过东西&#xff0c;以为安全就去下载…

.NET Core:跨平台和开源,让我在框架中脱颖而出

自从 2016 年微软发布了 .NET Core 1.0&#xff0c;至今 4 年的时间里&#xff0c;.NET Core 历经 7 个正式版本和几十个 Preview 版本。.NET Core 作为最通用的框架&#xff0c;和其他软件框架不同的是&#xff0c;它面向 Windows、Linux 和 MacOS 多个平台&#xff0c;在桌面…

vue实现侧边折叠菜单栏手风琴效果

在我们做管理后台亦或是产品流程时&#xff0c;总是需要一个菜单栏或者导航栏来架起我们的产品架构&#xff0c;那么&#xff0c;如何用vue实现侧边折叠导航栏呢&#xff1f;接下来将一一介绍。 请先看效果演示图。 步骤1&#xff1a;先架构整个页面的布局&#xff0c;撰写html…

程序员过关斩将--解决分布式session问题

微信搜一搜架构师修行之路session 说到 session&#xff0c;我相信每个程序员都不陌生&#xff0c;或多或少在项目中使用过。session 这个词&#xff0c;其实是一个抽象的概念&#xff0c;它不像 Cookie 那样有着明确的定义。当大多数程序员谈论 session 的时候&#xff0c;可能…

如何将nodejs项目程序部署到阿里云服务器上

将nodejs项目程序部署到阿里云服务器上一、概述二、具体步骤1、拥有自己的服务器2、下载Xshell3、 oneinstack配置web环境4、 XShell连接远程主机5、更新系统软件6、在服务器上安装node环境7、部署项目到服务器上8、安装pm2并启动nodejs项目三、快捷指令1、linux的常用命令2、p…

101. 对称二叉树023(BFS)

一&#xff1a;题目 二&#xff1a;上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullpt…

中移动完成透镜天线远距覆盖和降本增效试点

日前&#xff0c;中国移动研究院在官微上正式发布了《新型透镜天线进行首次高铁覆盖实验》一文。中国移动研究院、中国移动甘肃公司与西安海天天线科技股份有限公司联合开展的人工介质圆柱透镜天线在高铁、高速等线状纵深领域的长距覆盖取得突破性进展。两年以来&#xff0c;铁…

基于PHPEnv的本地环境搭建—PHP第一个项目:HelloWorld(从安装到运行)

1、安装软件 编程工具&#xff1a;Notepad 运行环境&#xff1a;phpEnv 2、用phpEnv建立本地运行环境 &#xff08;1&#xff09;官方下载phpEnv&#xff0c;运行phpEnv&#xff0c;启动服务。服务启动之后&#xff0c;apache和mysql变绿。如下图所示&#xff1a; &#xff0…

在idae中为什么用Module创建一个新的Maven项目的时候会被卡死

一:问题描述 然后就会卡死&#xff0c; 二&#xff1a;问题解决 我们会发现这里的路径是有问题的&#xff0c;idea自带的maven会卡死我们&#xff0c;因为下载jar包的速度慢的惊人 将其改为我们自己maven路径&#xff0c;下载速度会很快&#xff0c;便不会出现卡死的现象&a…

ASP.NET Core Blazor Webassembly 之 数据绑定

上一次我们学习了Blazor组件相关的知识&#xff08;Asp.net Core Blazor Webassembly - 组件&#xff09;。这次继续学习Blazor的数据绑定相关的知识。当代前端框架都离不开数据绑定技术。数据绑定技术以数据为主导来驱动UI界面&#xff0c;用户对数据的修改会实时提现在UI上&a…

PHP做二次开发:本机安装ThinkCMF系统

使用工具&#xff1a;phpEnv、TortoiseGit 具体步骤&#xff1a; 1.获取thinkcmf源代码 2.修改Hosts文件设置虚拟域名指向本机 3.配置apache建立本地站点 4.建立数据库 5.访问本地站点开始安装 第一步&#xff1a;获取thinkcmf源代码 1.打开浏览器访问gitee.com&#xff0c;搜…

107. 二叉树的层序遍历 II and 102. 二叉树的层序遍历 023(BFS模板题打两道)

一&#xff1a;题目 二&#xff1a;上码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullpt…

ASP.NET Core 注册单例方案

一个单例是没有公共构造函数的&#xff0c;只能通过静态的 Instance 属性获取&#xff0c;这是单例的标准初衷&#xff0c;一个单例是不想让别人调用它的构造函数的。但是 aspnetcore 中提供的 AddSingleton<TService, TImplementation>() &#xff0c;只提供了类型&…