C# 重构到工厂方法
我在函数中有一个代码块。我想重构它以应用工厂模式C# 重构到工厂方法,c#,design-patterns,dependency-injection,refactoring,C#,Design Patterns,Dependency Injection,Refactoring,我在函数中有一个代码块。我想重构它以应用工厂模式 IService service; switch (path) { case ServicePath.service1: service = new service1(log, mappingConfig); return await service.ServiceTask();
IService service;
switch (path)
{
case ServicePath.service1:
service = new service1(log, mappingConfig);
return await service.ServiceTask();
case ServicePath.service2:
service = new service2(log, mappingConfig);
return await service.ServiceTask();
case ServicePath.service3:
service = new service3(log, mappingConfig);
return await service.ServiceTask();
case ServicePath.service4:
service = new service4(log, mappingConfig);
return await service.ServiceTask();
}
我所做的是
class ServiceFactory
{
public static IService CreateService(String path, ILogger log, IConfig mappingConfig)
{
case ServicePath.service1:
return new service1(log, mappingConfig);
case ServicePath.service2:
return new service2(log, mappingConfig);
case ServicePath.service3:
return new service3(log, mappingConfig);
case ServicePath.service4:
return new service4(log, mappingConfig);
}
}
然后,调用方方法将
IService service = ServiceFactory.CreateService(path, log, mappingConfig);
return await serviceFeature.ServiceTask();
所以我关心的是,它仍然是一种工厂模式吗?如果不是,如何将其重构为工厂模式
我到处都在读,工厂模式和依赖注入做同样的工作。如何实现依赖项注入的代码?您目前使用的ServiceFactory方法本质上是一个抽象工厂,因为您在方法后面封装了一组相关对象的创建 有几种不同的方法可以通过依赖项注入获得类似的结果。这样做的一个主要好处是,您不再需要手动构造任何服务类。下面是一些使用.NET Core DI框架的示例: 注册工厂代表 您可以注册Func,它将接收字符串并返回iSeries设备的实例:
这样,您只需要注册这些类型。然后,您可以根据需要注入IServiceFactory。您目前使用的ServiceFactory方法本质上是一个抽象工厂,因为您将在方法后面封装相关对象集的创建 有几种不同的方法可以通过依赖项注入获得类似的结果。这样做的一个主要好处是,您不再需要手动构造任何服务类。下面是一些使用.NET Core DI框架的示例: 注册工厂代表 您可以注册Func,它将接收字符串并返回iSeries设备的实例:
这样,您只需要注册这些类型。然后可以根据需要注入IServiceFactory。重构后的代码类型为:简单工厂或静态工厂。如果您有多个工厂,它将是工厂模式。也就是说,ServiceFactory和ServiceFactory2也返回了一些iSeries
如果您已经知道如何先构造参数spath、log、mappingConfig,那么您应该坚持使用当前的SimpleFactory模式本身。如果参数对象及其状态是动态的,依赖注入对我来说更有意义。重构后的代码属于以下类型:简单工厂或静态工厂。如果您有多个工厂,它将是工厂模式。也就是说,ServiceFactory和ServiceFactory2也返回了一些iSeries
如果您已经知道如何先构造参数spath、log、mappingConfig,那么您应该坚持使用当前的SimpleFactory模式本身。如果参数对象及其状态是动态的,依赖注入对我来说更有意义,您可以为服务工厂创建一个接口并实现它,而不是使用静态方法。使用接口可以将此依赖项注入任何类中,并模拟它进行单元测试 公共接口IServiceFactory { IService CreateServicestring路径、ILogger日志、IConfig映射配置; } 实现可能如下 类服务工厂:IServiceFactory { 专用只读字典(地图),; 公共服务工厂 { _map=新字典; _map.AddServicePath.service1,log,mappingConfig=>newservice1log,mappingConfig; _map.AddServicePath.service2,log,mappingConfig=>newservice2log,mappingConfig; _map.AddServicePath.service3,log,mappingConfig=>newservice3log,mappingConfig; _map.AddServicePath.service4,log,mappingConfig=>newservice4log,mappingConfig; } 公共IService CreateServicestring路径、ILogger日志、IConfig映射配置 { return\u map.ContainsKeypath ?_映射[路径]日志,映射配置 :null;//或其他默认值 } }
您可以创建某种映射字典,而不是switch语句和多个case标签,它保存服务键和Func委托以创建具体的服务。在CreateService方法中,您要检查服务键是否存在于字典中,并调用Func委托以返回具体的服务实例,否则返回null您可以为服务工厂创建接口并实现它,而不是使用静态方法。使用接口可以将此依赖项注入任何类中,并模拟它进行单元测试 公共接口IServiceFactory { IService CreateServicestring路径、ILogger日志、IConfig映射配置; } 实现可能如下 类服务工厂:IServiceFactory { 专用只读字典(地图),; 公共服务工厂 { _map=新字典; _map.AddServicePath.service1,log,mappingConfig=>newservice1log,mappingConfig; _map.AddServicePath.service2,日志,mappingConfig=>new service2log,mappingConfig ; _map.AddServicePath.service3,log,mappingConfig=>newservice3log,mappingConfig; _map.AddServicePath.service4,log,mappingConfig=>newservice4log,mappingConfig; } 公共IService CreateServicestring路径、ILogger日志、IConfig映射配置 { return\u map.ContainsKeypath ?_映射[路径]日志,映射配置 :null;//或其他默认值 } }
您可以创建某种映射字典,而不是switch语句和多个case标签,它保存服务键和Func委托以创建具体的服务。在CreateService方法中,您正在检查字典中是否存在服务密钥,并调用Func委托以返回具体的服务实例,否则返回null您应该删除return Wait service.ServiceTask;从你的工厂里。我想他们被遗忘在那里了。是的,然后,这是工厂模式,但是你也可以考虑一个依赖注入容器来为你做所有的肮脏工作!旁注:如果您使用的是C8,那么使用@OguzOzgul可以大大减少这段代码,如何使用依赖项注入实现同样的效果?对ILogger和IConfig使用构造函数注入。您可以按名称注册类型。例如,AutoFac对此有支持。我认为所有DIC框架都会得到支持。相关:您应该删除return wait service.ServiceTask;从你的工厂里。我想他们被遗忘在那里了。是的,然后,这是工厂模式,但是你也可以考虑一个依赖注入容器来为你做所有的肮脏工作!旁注:如果您使用的是C8,那么使用@OguzOzgul可以大大减少这段代码,如何使用依赖项注入实现同样的效果?对ILogger和IConfig使用构造函数注入。您可以按名称注册类型。例如,AutoFac对此有支持。我认为所有DIC框架都将得到支持。相关:
services.AddTransient<Func<string, IService>>(sp => name =>
name switch
{
"A" => sp.GetService<ServiceA>(),
"B" => sp.GetService<ServiceB>(),
_ => throw new NotImplementedException()
});
public interface IServiceFactory
{
IService GetService(string name);
}
public class ServiceFactory : IServiceFactory
{
private readonly IServiceProvider _provider;
public ServiceFactory(IServiceProvider provider)
{
_provider = provider;
}
public IService GetService(string name) =>
name switch
{
"A" => _provider.GetService<ServiceA>(),
"B" => _provider.GetService<ServiceB>(),
_ => throw new NotImplementedException()
};
}