构造器的目的和构造函数一样,但是构造器可以提供丰富的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
public Container(List
{
_services = services;
}
}
//目标对象的构造者
public interface IContainerBuilder
{
//接口只提供一个通用方法,降低实现成本
void Add(ServiceDescriptor descriptor);
//构造目标对象
IContainer Build();
}
//实现构造者
public class ContainerBuilder : IContainerBuilder
{
private List
public void Add(ServiceDescriptor descriptor)
{
_services.Add(descriptor);
}
public IContainer Build()
{
return new Container(_services);
}
}
//扩展构造者,提供更加便捷的api
public static class IContainerBuilderExtensions
{
public static void AddTransient
{
builder.Add(new ServiceDescriptor(typeof(T), ServiceLifetime.Transient));
}
public static void AddScoped
{
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
public DbConnectionFactory(Dictionary
{
_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
services.AddScoped
services.AddSingleton(sp =>
{
var connections = new Dictionary
{
{ "s1", typeof(SqlDbConnection) },
{ "s2", typeof(MySqlDbConnection) }
};
return new DbConnectionFactory(connections);
});
var sp = services.BuildServiceProvider();
var factory = sp.GetRequiredService
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
public void Add(ILoggerProvider provider)
{
_providers.Add(provider);
}
public LoggerFactory Build()
{
return new LoggerFactory(_providers);
}
}
//这里用到了:代理模式,工厂模式,构造模式,提供模式
public class LoggerFactory
{
private IEnumerable
public LoggerFactory(IEnumerable
{
_providers = providers;
}
//通过委托的方式来构造
public static LoggerFactory Create(Action
{
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
public LoggerCollection(IEnumerable
{
_loggers = loggers;
}
public void Info(string message)
{
foreach (var logger in _loggers)
{
logger.Info(message);
}
}
}
}
代理模式侧重于对目标对象进行加强,通过实现目标对象的接口具备目标对象的能力。
一般通过实现和目标对象相同的接口来获得目标对象的能力
代理可以通过目标对象来简化实现成本,代理只负责编写加强逻辑
一般代理器只代理单个目标对象,我们把下面这个模式也可以归纳到代理模式,因为它能满足代理的许多特点比如加强、拥有目标对象的能力
思考我们需要一个LoggerCollection,需要实现ICollection
public interface ILogger { void Info(string message); } //代理模式必须要实现和目标相同的接口,并且可以注入目标对象 public class LoggerCollection : ILogger { private IEnumerable_loggers; public LoggerCollection(IEnumerable loggers) { _loggers = loggers; } public void Info(string message) { //加强逻辑 foreach (var logger in _loggers) { //具体实现由目标对象实现 logger.Info(message); } } }
装饰者模式侧重于添加装饰(方法),装饰者模式在Stream里面使用非常频繁,我们说流本质都是二进制。但是实际操作起来,有的是字符串。于是就有了TextStream、StreamReader把他们装饰成文本流,并提供新的api。