如何优化工厂模式参数传递?避免调用类注入过多依赖
优化方案
方案1:利用DI容器直接解析实现类
核心思路是让DI容器全权负责创建实现类并注入其依赖,彻底避免在CustomWorker中手动维护一堆服务依赖。只需要在CustomWorker中注入IServiceProvider,然后在工厂方法里根据条件获取对应的实现类即可。
修改后的代码示例:
// 先补全实现类的public构造函数(依赖注入要求构造函数可访问) public class class1Implementation : someAbstractClass { public class1Implementation(IHttpOneFirstService httpOneFirstService, IHttpOneSecondService httpOneSecondService, IDbOneService dbOneService) { _httpOneFirstService = httpOneFirstService; _httpOneSecondService = httpOneSecondService; _dbOneService = dbOneService; } private readonly IHttpOneFirstService _httpOneFirstService; private readonly IHttpOneSecondService _httpOneSecondService; private readonly IDbOneService _dbOneService; } // class2Implementation、class3Implementation同理补全public构造函数 public class CustomWorker : BackgroundService { private readonly IServiceProvider _serviceProvider; public CustomWorker(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } private someAbstractClass myFactory(int condition) { return condition switch { 0 => _serviceProvider.GetRequiredService<class1Implementation>(), 1 => _serviceProvider.GetRequiredService<class2Implementation>(), _ => _serviceProvider.GetRequiredService<class3Implementation>(), }; } }
这样CustomWorker只需要依赖IServiceProvider,不用再注入9个冗余服务,所有实现类的依赖都由DI容器自动处理。
方案2:创建独立的工厂类
把工厂逻辑抽离到专门的工厂类中,让CustomWorker只依赖这个工厂接口,进一步解耦业务逻辑和实例创建逻辑。
代码示例:
// 定义工厂接口 public interface ISomeAbstractFactory { someAbstractClass Create(int condition); } // 实现工厂类 public class SomeAbstractFactory : ISomeAbstractFactory { private readonly IServiceProvider _serviceProvider; public SomeAbstractFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public someAbstractClass Create(int condition) { return condition switch { 0 => _serviceProvider.GetRequiredService<class1Implementation>(), 1 => _serviceProvider.GetRequiredService<class2Implementation>(), _ => _serviceProvider.GetRequiredService<class3Implementation>(), }; } } // 修改CustomWorker public class CustomWorker : BackgroundService { private readonly ISomeAbstractFactory _factory; public CustomWorker(ISomeAbstractFactory factory) { _factory = factory; } // 调用工厂方法获取实例 private someAbstractClass GetImplementation(int condition) { return _factory.Create(condition); } }
记得在DI容器中注册相关服务:
// Program.cs中注册 builder.Services.AddScoped<ISomeAbstractFactory, SomeAbstractFactory>(); builder.Services.AddScoped<class1Implementation>(); builder.Services.AddScoped<class2Implementation>(); builder.Services.AddScoped<class3Implementation>(); // 同时注册各个HTTP和DB服务 builder.Services.AddScoped<IHttpOneFirstService, HttpOneFirstService>(); // ...其他服务同理注册
这个方案的优势是工厂逻辑和CustomWorker完全分离,后续新增实现类只需要修改工厂类,不会影响业务代码。
方案3:使用Keyed Services关联条件(.NET 8+)
如果希望更直观地关联条件和实现类,可以用.NET 8新增的Keyed Services特性,通过指定Key来区分不同实现类,再根据条件匹配Key获取实例。
代码示例:
// 注册时指定Key builder.Services.AddKeyedScoped<someAbstractClass, class1Implementation>("Impl1"); builder.Services.AddKeyedScoped<someAbstractClass, class2Implementation>("Impl2"); builder.Services.AddKeyedScoped<someAbstractClass, class3Implementation>("Impl3"); // 修改工厂类中的创建逻辑 public someAbstractClass Create(int condition) { var key = condition switch { 0 => "Impl1", 1 => "Impl2", _ => "Impl3", }; return _serviceProvider.GetRequiredKeyedService<someAbstractClass>(key); }
这种方式让条件和实现类的映射关系更清晰,维护起来更方便。
内容的提问来源于stack exchange,提问作者TryHard
相关产品推荐
相关产品推荐

