使用DI和IoC的工厂方法

我熟悉这些模式,但仍然不知道如何处理以下情况:

public class CarFactory

{

public CarFactory(Dep1,Dep2,Dep3,Dep4,Dep5,Dep6)

{

}

public ICar CreateCar(type)

{

switch(type)

{

case A:

return new Car1(Dep1,Dep2,Dep3);

break;

case B:

return new Car2(Dep4,Dep5,Dep6);

break;

}

}

}

通常,问题在于需要注入的引用数量。如果有更多的汽车,情况将会更糟。

我想到的第一种方法是在工厂构造函数中注入Car1和Car2,但是这与工厂方法相反,因为工厂将始终返回相同的对象。第二种方法是注入servicelocator,但是它到处都是反模式。怎么解决呢?

回答:

替代方法1:

public class CarFactory

{

public CarFactory(IContainer container)

{

_container = container;

}

public ICar CreateCar(type)

{

switch(type)

{

case A:

return _container.Resolve<ICar1>();

break;

case B:

return _container.Resolve<ICar2>();

break;

}

}

}

替代方法2(由于树中过多的依赖关系而很难使用):

public class CarFactory

{

public CarFactory()

{

}

public ICar CreateCar(type)

{

switch(type)

{

case A:

return new Car1(new Dep1(),new Dep2(new Dep683(),new Dep684()),....)

break;

case B:

return new Car2(new Dep4(),new Dep5(new Dep777(),new Dep684()),....)

break;

}

}

}

回答:

在工厂内部有一个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 code, 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));

以上是 使用DI和IoC的工厂方法 的全部内容, 来源链接: utcz.com/qa/397888.html

回到顶部