在工厂内部有一个switch case语句是一种代码味道。有趣的是,您似乎根本没有专注于解决该问题。
针对这种情况的最佳,最直接的DI解决方案是策略模式。它允许您的DI容器将依赖项注入到它们所属的工厂实例中,而不会使具有这些依赖项的其他类变得混乱,也不必诉诸服务定位器。
介面
public interface ICarFactory{ ICar CreateCar(); bool AppliesTo(Type type);}public interface ICarStrategy{ ICar CreateCar(Type type);}工厂工厂
public class Car1Factory : ICarFactory{ private readonly IDep1 dep1; private readonly IDep2 dep2; private readonly IDep3 dep3; public Car1Factory(IDep1 dep1, IDep2 dep2, IDep3 dep3) { if (dep1 == null) throw new ArgumentNullException("dep1"); if (dep2 == null) throw new ArgumentNullException("dep2"); if (dep3 == null) throw new ArgumentNullException("dep3"); this.dep1 = dep1; this.dep2 = dep2; this.dep3 = dep3; } public ICar CreateCar() { return new Car1(this.dep1, this.dep2, this.dep3); } public bool AppliesTo(Type type) { return typeof(Car1).Equals(type); }}public class Car2Factory : ICarFactory{ private readonly IDep4 dep4; private readonly IDep5 dep5; private readonly IDep6 dep6; public Car1Factory(IDep4 dep4, IDep5 dep5, IDep6 dep6) { if (dep4 == null) throw new ArgumentNullException("dep4"); if (dep5 == null) throw new ArgumentNullException("dep5"); if (dep6 == null) throw new ArgumentNullException("dep6"); this.dep4 = dep4; this.dep5 = dep5; this.dep6 = dep6; } public ICar CreateCar() { return new Car2(this.dep4, this.dep5, this.dep6); } public bool AppliesTo(Type type) { return typeof(Car2).Equals(type); }}战略
public class CarStrategy : ICarStrategy{ private readonly ICarFactory[] carFactories; public CarStrategy(ICarFactory[] carFactories) { if (carFactories == null) throw new ArgumentNullException("carFactories"); this.carFactories = carFactories; } public ICar CreateCar(Type type) { var carFactory = this.carFactories .FirstOrDefault(factory => factory.AppliesTo(type)); if (carFactory == null) { throw new Exception("type not registered"); } return carFactory.CreateCar(); }}用法
// I am showing this in pre, but you would normally // do this with your DI container in your composition // root, and the instance would be created by injecting // it somewhere.var strategy = new CarStrategy(new ICarFactory[] { new Car1Factory(dep1, dep2, dep3), new Car2Factory(dep4, dep5, dep6) });// And then once it is injected, you would simply do this.// Note that you could use a magic string or some other // data type as the parameter if you prefer.var car1 = strategy.CreateCar(typeof(Car1));var car2 = strategy.CreateCar(typeof(Car2));请注意,由于没有switch
case语句,因此可以在不更改设计的情况下将其他工厂添加到策略中,并且这些工厂中的每个工厂都可以具有自己的依赖性,这些依赖性由DI容器注入。
var strategy = new CarStrategy(new ICarFactory[] { new Car1Factory(dep1, dep2, dep3), new Car2Factory(dep4, dep5, dep6), new Car3Factory(dep7, dep8, dep9) });var car1 = strategy.CreateCar(typeof(Car1));var car2 = strategy.CreateCar(typeof(Car2));var car3 = strategy.CreateCar(typeof(Car3));


