当前位置: 首页 > 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。

http://www.lryc.cn/news/131263.html

相关文章:

  • FFmpeg参数说明FFmpegAndroid饺子视频播放器
  • DNS入门学习:DNS解析生效问题(中科三方)
  • Ubuntu22.04编译安装Mysql5.7.35
  • C++音乐播放系统
  • Django笔记之log日志记录详解
  • vue局部打印多页面pdf
  • 指定或降低Rust 工具链的版本
  • 数据驱动成功:商城小程序分析与改进
  • 基于GUI的卷积神经网络和长短期神经网络的语音识别系统,卷积神经网的原理,长短期神经网络的原理
  • Docker环境安装elasticsearch和kibana
  • 【剖析STL】vector
  • Redis、Memcache和MongoDB的区别
  • 2023中大ACM游记
  • 记一次线上OOM事故
  • Learning to Super-resolve Dynamic Scenes for Neuromorphic Spike Camera论文笔记
  • 怎么使用手机远程控制Win10电脑?
  • W6100-EVB-PICO 做UDP Client 进行数据回环测试(八)
  • Typora 相对路径保存图片以及 Gitee 无法显示图片
  • 深入探索:Kali Linux 网络安全之旅
  • Python 实现语音转文本
  • 使用DSA、ECDSA、Ed25519 和 rfc6979_rust实现高安全性的数字签名
  • “深入探索JVM内部机制:解密Java虚拟机的奥秘“
  • css3新增属性
  • 自动驾驶港口车辆故障及事故处理机制
  • 【leetcode 力扣刷题】快乐数/可被k整除的最小整数(可能存在无限循环的技巧题)
  • Python 的下一代 HTTP 客户端
  • 网络安全---webshell实践
  • 论AI GPT跨境贸易架构及其应用
  • github的CodeSpace如何对外提供TCP 端口服务?
  • 借助Midjourney创作龙九子图