IOC容器的基础功能设计模式
构造模式
-
构造器的目的和构造函数一样,但是构造器可以提供丰富的api来简化对象的构造
-
构造模式用于简化被构造对象的创建,通过提供一大堆的api来丰富简化构造过程,增加调用者的体验。
-
构造者需要提供一个Build方法用于构建和返回将要构造的对象实列。
-
在容器中一般需要提供一个公开的IServiceCollection类型的属性,用于注册服务。
-
IServiceCollection是构造者模式
*/
public class DbContext
{
}
public enum ServiceLifetime
{
Transient,
Scoped,
}
public class ServiceDescriptor
{
public Type ServiceType { get; }
public ServiceLifetime Lifetime { get; }
public ServiceDescriptor(Type serviceType, ServiceLifetime lifetime)
{
ServiceType = serviceType;
Lifetime = lifetime;
}
}
//目标对象
public interface IContainer
{
}
//如果直接创建成本很高,体验很差
public class Container : IContainer
{
private List<ServiceDescriptor> _services = new();
public Container(List<ServiceDescriptor> services)
{
_services = services;
}
}
//目标对象的构造者
public interface IContainerBuilder
{
//接口只提供一个通用方法,降低实现成本
void Add(ServiceDescriptor descriptor);
//构造目标对象
IContainer Build();
}
//实现构造者
public class ContainerBuilder : IContainerBuilder
{
private List<ServiceDescriptor> _services = new List<ServiceDescriptor> ();
public void Add(ServiceDescriptor descriptor)
{
_services.Add(descriptor);
}
public IContainer Build()
{
return new Container(_services);
}
}
//扩展构造者,提供更加便捷的api
public static class IContainerBuilderExtensions
{
public static void AddTransient<T>(this IContainerBuilder builder)
{
builder.Add(new ServiceDescriptor(typeof(T), ServiceLifetime.Transient));
}
public static void AddScoped<T>(this IContainerBuilder builder)
{
builder.Add(new ServiceDescriptor(typeof(T), ServiceLifetime.Scoped));
}
}
工厂模式
-
工厂模式侧重于对象的管理(创建销毁),一般提供一个Create方法,支持命名创建。
-
通过上面的学习我们发现IOC有一个弊端,就是他是通过服务类型的解析服务的。有些情况下我们需要通过命名的方式来解析服务。此时可以使用工厂模式。
-
IServiceProvider也是工厂模式
public interface IDbConnection
{
}
public class MySqlDbConnection : IDbConnection
{
}
public class SqlDbConnection : IDbConnection
{
}
//如果是一个重量级的工厂,建议注册成单实例
public class DbConnectionFactory
{
private Dictionary<string, Type> _connections;
public DbConnectionFactory(Dictionary<string, Type> connections)
{
_serviceProvider = provider;
_connections = connections;
}
public IDbConnection? Create(IServiceProvider serviceProvider, string name)
{
if (_connections.TryGetValue(name, out Type? connectionType))
{
return serviceProvider.GetRequiredService(connectionType) as IDbConnection;
}
return default;
}
}
//测试
var services = new ServiceCollection();
services.AddScoped<MySqlDbConnection>();
services.AddScoped<SqlDbConnection>();
services.AddSingleton(sp =>
{
var connections = new Dictionary<string, Type>
{
{ "s1", typeof(SqlDbConnection) },
{ "s2", typeof(MySqlDbConnection) }
};
return new DbConnectionFactory(connections);
});
var sp = services.BuildServiceProvider();
var factory = sp.GetRequiredService<DbConnectionFactory>();
var s1 = factory.Create(sp, "s1");
var s2 = factory.Create(sp, "s2");
提供模式
-
如果看到提供者模式,说明我们可以提供多个方案,支持多实现
-
一般通过工厂来管理提供者,用以支持命名实列
public interface ILogger
{
void Info(string message);
}
public interface ILoggerProvider
{
ILogger CreateLogger(string name);
}
//日志提供方案1
public class ConsoleLoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string name)
{
return new ConsoleLogger(name);
}
class ConsoleLogger : ILogger
{
private string _name;
public ConsoleLogger(string name)
{
_name = name;
}
public void Info(string message)
{
Console.WriteLine($"{_name}:{message}");
}
}
}
//日志提供方案2
public class DebugLoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string name)
{
return new DebugLogger(name);
}
class DebugLogger : ILogger
{
private string _name;
public DebugLogger(string name)
{
_name = name;
}
public void Info(string message)
{
Debug.WriteLine($"{_name}:{message}");
}
}
}
public class LoggerFactoryBuilder
{
private List<ILoggerProvider> _providers = new ();
public void Add(ILoggerProvider provider)
{
_providers.Add(provider);
}
public LoggerFactory Build()
{
return new LoggerFactory(_providers);
}
}
//这里用到了:代理模式,工厂模式,构造模式,提供模式
public class LoggerFactory
{
private IEnumerable<ILoggerProvider> _providers = new ();
public LoggerFactory(IEnumerable<ILoggerProvider> providers)
{
_providers = providers;
}
//通过委托的方式来构造
public static LoggerFactory Create(Action<LoggerFactoryBuilder> configure)
{
var builder = new LoggerFactoryBuilder();
configure(builder);
return builder.Build();
}
public void AddProvider(ILoggerProvider provider)
{
_providers.Add(provider);
}
public ILogger Create(string name)
{
var loggers = _providers.Select(s=>s.CreateLogger(name));
return new LoggerCollection(loggers);
}
//代理模式
class LoggerCollection : ILogger
{
private IEnumerable<ILogger> _loggers;
public LoggerCollection(IEnumerable<ILogger> loggers)
{
_loggers = loggers;
}
public void Info(string message)
{
foreach (var logger in _loggers)
{
logger.Info(message);
}
}
}
}
代理模式
-
代理模式侧重于对目标对象进行加强,通过实现目标对象的接口具备目标对象的能力。
-
一般通过实现和目标对象相同的接口来获得目标对象的能力
-
代理可以通过目标对象来简化实现成本,代理只负责编写加强逻辑
-
一般代理器只代理单个目标对象,我们把下面这个模式也可以归纳到代理模式,因为它能满足代理的许多特点比如加强、拥有目标对象的能力
-
思考我们需要一个LoggerCollection,需要实现ICollection<ILogger>接口,如何降低实现成本?
public interface ILogger
{void Info(string message);
}
//代理模式必须要实现和目标相同的接口,并且可以注入目标对象
public class LoggerCollection : ILogger
{private IEnumerable<ILogger> _loggers;public LoggerCollection(IEnumerable<ILogger> loggers){_loggers = loggers;}
public void Info(string message){ //加强逻辑foreach (var logger in _loggers){//具体实现由目标对象实现logger.Info(message);}}
}
装饰者模式
装饰者模式侧重于添加装饰(方法),装饰者模式在Stream里面使用非常频繁,我们说流本质都是二进制。但是实际操作起来,有的是字符串。于是就有了TextStream、StreamReader把他们装饰成文本流,并提供新的api。
相关文章:
IOC容器的基础功能设计模式
构造模式 构造器的目的和构造函数一样,但是构造器可以提供丰富的api来简化对象的构造 构造模式用于简化被构造对象的创建,通过提供一大堆的api来丰富简化构造过程,增加调用者的体验。 构造者需要提供一个Build方法用于构建和返回将要构造的…...
FFmpeg参数说明FFmpegAndroid饺子视频播放器
FFmpegAndroid https://github.com/xufuji456/FFmpegAndroid https://github.com/lipangit/JiaoZiVideoPlayer/tree/develop 饺子视频播放器 ffmpeg 不是内部或外部命令,也不是可运行的程序 或批处理文件 http://www.360doc.com/content/21/0204/15/54508727_9606…...
DNS入门学习:DNS解析生效问题(中科三方)
在修改域名解析记录或DNS服务器之后,DNS解析并不会立即生效,这给很多网站管理者带来了很多困扰,了解DNS解析生效原理以及不同情况下DNS解析生效时间,对于网站管理工作有很大帮助。本文中科三方针对不同情况下DNS解析生效时间做下简…...
Ubuntu22.04编译安装Mysql5.7.35
新升级的ubuntu22.04版本,该版本默认openssl已经升级到3.0,所以编译过程遇到一些问题记录一下。 编译步骤: 安装依赖 gcc g已经安装过就不需要再安装了。 apt-get install cmake apt-get install libaio-dev apt-get install libncurses5…...
C++音乐播放系统
C音乐播放系统 音乐的好处c发出声音乐谱与赫兹对照把歌打到c上 学习c的同学们都知道,c是一个一本正经的编程语言,因该没有人用它来做游戏、做病毒、做…做…做音乐播放系统吧!! 音乐的好处 提升情绪:音乐能够影响我们…...
Django笔记之log日志记录详解
以下是一个简单的 logging 模块示例,可以先预览一下,接下来会详细介绍各个模块的具体功能: LOGGING {version: 1,disable_existing_loggers: False,formatters: {verbose: {format: %(levelname)s %(message)s,}},handlers: {file_1: {leve…...
vue局部打印多页面pdf
技术背景 html打印程pdf,使用的官方提供的window.print()打印的样式 media print {} 方法一 const printContent this.$refs.bodyright;var textInput printContent.getElementsByTagName("input");for (var i 0; i < textInput.length; i) {textInput[i].se…...
指定或降低Rust 工具链的版本
要更改 Rust 工具链的版本,您可以使用以下命令之一: rustup default stable:使用 stable 版本的 Rust 工具链作为默认版本。rustup default beta:使用 beta 版本的 Rust 工具链作为默认版本。rustup default nightly:使…...
数据驱动成功:商城小程序分析与改进
在当今数字化时代,商城小程序成为了企业与消费者之间互动的重要途径。然而,一个成功的商城小程序不仅仅是一个购物平台,更需要通过数据分析不断进行改进和优化,以提升用户体验和营销效果。本文将深入探讨如何利用数据驱动的方式进…...
基于GUI的卷积神经网络和长短期神经网络的语音识别系统,卷积神经网的原理,长短期神经网络的原理
目录 背影 卷积神经网络CNN的原理 卷积神经网络CNN的定义 卷积神经网络CNN的神经元 卷积神经网络CNN的激活函数 卷积神经网络CNN的传递函数 长短期神经网络的原理 基于GUI的卷积神经网络和长短期神经网络的语音识别系统 代码下载链接:基于MATLABGUI编程的卷积神经网络和长短期…...
Docker环境安装elasticsearch和kibana
一、安装elasticsearch 创建es-network,让es、kibana在同一个网段: docker network create --driverbridge --subnet192.168.1.10/24 es-network运行elasticsearch docker run -d \ --name elasticsearch \ # 容器名 --hostname elasticsearch # 主机…...
【剖析STL】vector
vector的介绍及使用 1.1 vector的介绍 cplusplus.com/reference/vector/vector/ vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是…...
Redis、Memcache和MongoDB的区别
>>Memcached Memcached的优点: Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key、value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右)。适用于最大程度…...
2023中大ACM游记
游记 中午快十二点时才到了广州六中,在附近吃了塔斯汀汉堡,味道还不错。 十二点半才卡点到了考场,本以为来晚了,但老师说比赛时间延迟,十二点五十才开场。 三个人用一台电脑,这种比赛方式还是第一次遇到…...
记一次线上OOM事故
OOM 问题 linux内核有个机制叫OOM killer(Out-Of-Memory killer),当系统需要申请内存却申请不到时,OOM killer会检查当前进程中占用内存最大者,将其杀掉,腾出内存保障系统正常运行。 一般而言,一个应用的内存逐渐增加&…...
Learning to Super-resolve Dynamic Scenes for Neuromorphic Spike Camera论文笔记
摘要 脉冲相机使用了“integrate and fire”机制来生成连续的脉冲流,以极高的时间分辨率来记录动态光照强度。但是极高的时间分辨率导致了受限的空间分辨率,致使重建出的图像无法很好保留原始场景的细节。为了解决这个问题,这篇文章提出了Sp…...
怎么使用手机远程控制Win10电脑?
可以使用手机远程控制电脑吗? “近期,我将出差一段时间。问题是,我希望能够从很远的地方浏览家里电脑上的一些东西,但我不会一直随身携带笨重的笔记本电脑。我可以手机远程访问Windows电脑吗? ” 当然&am…...
W6100-EVB-PICO 做UDP Client 进行数据回环测试(八)
前言 上一章我们用开发板作为UDP Server进行数据回环测试,本章我们让我们的开发板作为UDP Client进行数据回环测试。 连接方式 使开发板和我们的电脑处于同一网段: 开发板通过交叉线直连主机开发板和主机都接在路由器LAN口 测试工具 网路调试工具&a…...
Typora 相对路径保存图片以及 Gitee 无法显示图片
目录 Typora 相对路径保存图片 Gitee 无法显示图片 Typora 相对路径保存图片 Step1:修改 Typora 的偏好设置 自动在当前目录创建名为 "./${filename}.assets" 的文件夹粘贴图片到 md 中时,图片会自动另存到 "./${filename}.assets&qu…...
深入探索:Kali Linux 网络安全之旅
目录 前言 访问官方网站 导航到下载页面 启动后界面操作 前言 "Kali" 可能指的是 Kali Linux,它是一种基于 Debian 的 Linux 发行版,专门用于渗透测试、网络安全评估、数字取证和相关的安全任务。Kali Linux 旨在提供一系列用于测试网络和…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇
根据 QYResearch 发布的市场报告显示,全球市场规模预计在 2031 年达到 9848 万美元,2025 - 2031 年期间年复合增长率(CAGR)为 3.7%。在竞争格局上,市场集中度较高,2024 年全球前十强厂商占据约 74.0% 的市场…...
02-性能方案设计
需求分析与测试设计 根据具体的性能测试需求,确定测试类型,以及压测的模块(web/mysql/redis/系统整体)前期要与相关人员充分沟通,初步确定压测方案及具体的性能指标QA完成性能测试设计后,需产出测试方案文档发送邮件到项目组&…...
