Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 重构到工厂方法_C#_Design Patterns_Dependency Injection_Refactoring - Fatal编程技术网

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()
        };
}