当前位置: 首页 > news >正文

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容器的基础功能设计模式

构造模式 构造器的目的和构造函数一样&#xff0c;但是构造器可以提供丰富的api来简化对象的构造 构造模式用于简化被构造对象的创建&#xff0c;通过提供一大堆的api来丰富简化构造过程&#xff0c;增加调用者的体验。 构造者需要提供一个Build方法用于构建和返回将要构造的…...

FFmpeg参数说明FFmpegAndroid饺子视频播放器

FFmpegAndroid https://github.com/xufuji456/FFmpegAndroid https://github.com/lipangit/JiaoZiVideoPlayer/tree/develop 饺子视频播放器 ffmpeg 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件 http://www.360doc.com/content/21/0204/15/54508727_9606…...

DNS入门学习:DNS解析生效问题(中科三方)

在修改域名解析记录或DNS服务器之后&#xff0c;DNS解析并不会立即生效&#xff0c;这给很多网站管理者带来了很多困扰&#xff0c;了解DNS解析生效原理以及不同情况下DNS解析生效时间&#xff0c;对于网站管理工作有很大帮助。本文中科三方针对不同情况下DNS解析生效时间做下简…...

Ubuntu22.04编译安装Mysql5.7.35

新升级的ubuntu22.04版本&#xff0c;该版本默认openssl已经升级到3.0&#xff0c;所以编译过程遇到一些问题记录一下。 编译步骤&#xff1a; 安装依赖 gcc g已经安装过就不需要再安装了。 apt-get install cmake apt-get install libaio-dev apt-get install libncurses5…...

C++音乐播放系统

C音乐播放系统 音乐的好处c发出声音乐谱与赫兹对照把歌打到c上 学习c的同学们都知道&#xff0c;c是一个一本正经的编程语言&#xff0c;因该没有人用它来做游戏、做病毒、做…做…做音乐播放系统吧&#xff01;&#xff01; 音乐的好处 提升情绪&#xff1a;音乐能够影响我们…...

Django笔记之log日志记录详解

以下是一个简单的 logging 模块示例&#xff0c;可以先预览一下&#xff0c;接下来会详细介绍各个模块的具体功能&#xff1a; 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 工具链的版本&#xff0c;您可以使用以下命令之一&#xff1a; rustup default stable&#xff1a;使用 stable 版本的 Rust 工具链作为默认版本。rustup default beta&#xff1a;使用 beta 版本的 Rust 工具链作为默认版本。rustup default nightly&#xff1a;使…...

数据驱动成功:商城小程序分析与改进

在当今数字化时代&#xff0c;商城小程序成为了企业与消费者之间互动的重要途径。然而&#xff0c;一个成功的商城小程序不仅仅是一个购物平台&#xff0c;更需要通过数据分析不断进行改进和优化&#xff0c;以提升用户体验和营销效果。本文将深入探讨如何利用数据驱动的方式进…...

基于GUI的卷积神经网络和长短期神经网络的语音识别系统,卷积神经网的原理,长短期神经网络的原理

目录 背影 卷积神经网络CNN的原理 卷积神经网络CNN的定义 卷积神经网络CNN的神经元 卷积神经网络CNN的激活函数 卷积神经网络CNN的传递函数 长短期神经网络的原理 基于GUI的卷积神经网络和长短期神经网络的语音识别系统 代码下载链接:基于MATLABGUI编程的卷积神经网络和长短期…...

Docker环境安装elasticsearch和kibana

一、安装elasticsearch 创建es-network&#xff0c;让es、kibana在同一个网段&#xff1a; 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是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问&#xff0c;和数组一样高效。但是…...

Redis、Memcache和MongoDB的区别

>>Memcached Memcached的优点&#xff1a; Memcached可以利用多核优势&#xff0c;单实例吞吐量极高&#xff0c;可以达到几十万QPS&#xff08;取决于key、value的字节大小以及服务器硬件性能&#xff0c;日常环境中QPS高峰大约在4-6w左右&#xff09;。适用于最大程度…...

2023中大ACM游记

游记 中午快十二点时才到了广州六中&#xff0c;在附近吃了塔斯汀汉堡&#xff0c;味道还不错。 十二点半才卡点到了考场&#xff0c;本以为来晚了&#xff0c;但老师说比赛时间延迟&#xff0c;十二点五十才开场。 三个人用一台电脑&#xff0c;这种比赛方式还是第一次遇到…...

记一次线上OOM事故

OOM 问题 linux内核有个机制叫OOM killer(Out-Of-Memory killer)&#xff0c;当系统需要申请内存却申请不到时&#xff0c;OOM killer会检查当前进程中占用内存最大者&#xff0c;将其杀掉&#xff0c;腾出内存保障系统正常运行。 一般而言&#xff0c;一个应用的内存逐渐增加&…...

Learning to Super-resolve Dynamic Scenes for Neuromorphic Spike Camera论文笔记

摘要 脉冲相机使用了“integrate and fire”机制来生成连续的脉冲流&#xff0c;以极高的时间分辨率来记录动态光照强度。但是极高的时间分辨率导致了受限的空间分辨率&#xff0c;致使重建出的图像无法很好保留原始场景的细节。为了解决这个问题&#xff0c;这篇文章提出了Sp…...

怎么使用手机远程控制Win10电脑?

可以使用手机远程控制电脑吗&#xff1f; “近期&#xff0c;我将出差一段时间。问题是&#xff0c;我希望能够从很远的地方浏览家里电脑上的一些东西&#xff0c;但我不会一直随身携带笨重的笔记本电脑。我可以手机远程访问Windows电脑吗&#xff1f; ” 当然&am…...

W6100-EVB-PICO 做UDP Client 进行数据回环测试(八)

前言 上一章我们用开发板作为UDP Server进行数据回环测试&#xff0c;本章我们让我们的开发板作为UDP Client进行数据回环测试。 连接方式 使开发板和我们的电脑处于同一网段&#xff1a; 开发板通过交叉线直连主机开发板和主机都接在路由器LAN口 测试工具 网路调试工具&a…...

Typora 相对路径保存图片以及 Gitee 无法显示图片

目录 Typora 相对路径保存图片 Gitee 无法显示图片 Typora 相对路径保存图片 Step1&#xff1a;修改 Typora 的偏好设置 自动在当前目录创建名为 "./${filename}.assets" 的文件夹粘贴图片到 md 中时&#xff0c;图片会自动另存到 "./${filename}.assets&qu…...

深入探索:Kali Linux 网络安全之旅

目录 前言 访问官方网站 导航到下载页面 启动后界面操作 前言 "Kali" 可能指的是 Kali Linux&#xff0c;它是一种基于 Debian 的 Linux 发行版&#xff0c;专门用于渗透测试、网络安全评估、数字取证和相关的安全任务。Kali Linux 旨在提供一系列用于测试网络和…...

Qt 5.9.4 + NDK r10e + JDK 1.8:一个老项目Android移植的稳定环境搭建实录

Qt 5.9.4 NDK r10e JDK 1.8&#xff1a;构建Android移植的黄金环境组合 在移动开发领域&#xff0c;技术迭代速度令人眼花缭乱&#xff0c;但对于那些需要维护历史Qt项目的开发者来说&#xff0c;稳定往往比新潮更重要。我曾接手过一个2017年开发的工业控制软件项目&#xff…...

Wiki.js日志系统终极指南:从记录到安全监控的全面解析

Wiki.js日志系统终极指南&#xff1a;从记录到安全监控的全面解析 【免费下载链接】wiki- Wiki.js | A modern and powerful wiki app built on Node.js 项目地址: https://gitcode.com/GitHub_Trending/wiki78/wiki- 当您的团队在Wiki.js中协作编辑文档时&#xff0c;是…...

启动 SAP Fiori Launchpad Designer:把 URL、scope、client 与排障思路一次讲透

在 SAP Fiori 项目里,很多团队花了不少时间做完前置配置,却在真正打开 Launchpad Designer 的那一刻卡住了:地址到底怎么拼?CONF 和 CUST 应该怎么选?为什么同一套内容在不同 client 里表现不一样?如果页面迟迟加载不出来,问题究竟出在 SAPUI5、ICF、OData,还是权限本身…...

电路原理与情感关系的电子工程解读

电子工程视角下的电路与人生哲学1. 电路元件与情感关系的类比分析1.1 信号放大器与初恋心理初恋阶段的心理状态类似于简单的信号放大器系统。在这个模型中&#xff0c;情感输入信号被高度放大&#xff0c;微小的快乐信号能产生极大的幸福感输出&#xff0c;同样微小的伤害信号也…...

终极桌面伴侣BongoCat:让键盘鼠标操作变得生动有趣的虚拟猫咪

终极桌面伴侣BongoCat&#xff1a;让键盘鼠标操作变得生动有趣的虚拟猫咪 【免费下载链接】BongoCat 让呆萌可爱的 Bongo Cat 陪伴你的键盘敲击与鼠标操作&#xff0c;每一次输入都充满趣味与活力&#xff01; 项目地址: https://gitcode.com/gh_mirrors/bong/BongoCat …...

AutoGen Studio实战分享:用Qwen3-4B模型实现自动化任务处理

AutoGen Studio实战分享&#xff1a;用Qwen3-4B模型实现自动化任务处理 1. AutoGen Studio简介与核心价值 AutoGen Studio是一个低代码界面&#xff0c;专为快速构建AI代理而设计。它基于AutoGen AgentChat构建&#xff0c;提供了高级API用于创建多代理应用。这个工具的核心价…...

GTE中文-large多任务能力展示:同一输入文本同步输出NER标签+情感得分+分类结果

GTE中文-large多任务能力展示&#xff1a;同一输入文本同步输出NER标签情感得分分类结果 提示&#xff1a;本文展示的GTE中文-large模型多任务能力基于ModelScope的iic/nlp_gte_sentence-embedding_chinese-large镜像实现&#xff0c;所有示例均为真实运行结果。 1. 多任务模型…...

Xftp访问服务器文件夹报错?可能是你Xshell打开的方式不对(附正确操作截图)

Xftp访问服务器文件夹报错&#xff1f;可能是你Xshell打开的方式不对&#xff08;附正确操作截图&#xff09; 当你使用Xftp连接服务器时&#xff0c;突然遇到"无法显示远程文件夹"的报错&#xff0c;这往往不是Xftp本身的问题&#xff0c;而是权限和会话上下文在作…...

Pixel Dimension Fissioner 与YOLOv8协同:智能图像分析与内容生成

Pixel Dimension Fissioner 与YOLOv8协同&#xff1a;智能图像分析与内容生成 1. 场景引入&#xff1a;当计算机视觉遇上内容生成 想象一下这样的场景&#xff1a;你拍了一张街景照片上传到系统&#xff0c;几秒钟后&#xff0c;系统不仅识别出了照片中的咖啡馆、行道树和行人…...

罗技鼠标宏:专业级压枪系统构建指南

罗技鼠标宏&#xff1a;专业级压枪系统构建指南 【免费下载链接】logitech-pubg PUBG no recoil script for Logitech gaming mouse / 绝地求生 罗技 鼠标宏 项目地址: https://gitcode.com/gh_mirrors/lo/logitech-pubg 在竞技射击游戏中&#xff0c;精准控制武器后坐力…...