简单的工厂和IOC

时间:2016-07-21 06:35:34

标签: c# design-patterns inversion-of-control factory

我有class A{} class B:A{} class C:A{}class D{} D有方法需要使用B和需要使用C的方法。

将来我可能会有更多继承自A需要使用的D的课程

D应该有如下构造函数:

  1. 公开D(B b, C c)

  2. A应该获得一个简单的工厂(F),它将返回 正确的课程。然后构造函数将是public D(F f)

  3. F将使用CreateInstance方法获取枚举并返回正确的类型。

    完全注射将保留组合物中的所有根。 简单的工厂会简化构造函数。

2 个答案:

答案 0 :(得分:2)

您需要注意的问题是通过工厂方法引入不透明的依赖项。

此时,D依赖于B C.使用如下构造函数:

public D(B b, C c)
{
}

使依赖项透明。即它清楚这个班级需要做什么工作,这些东西可以直接提供。此外,自动化测试更容易,因为您可以直接提供假货,而无需提供假冒工厂提供其他假货。

使用工厂降低了这种清晰度,但通过减少必须传递的依赖项数量,确实增加了便利性和一定程度的面向未来。

就个人而言,我会坚持直接提供依赖项,直到构造函数签名不实用或明显需要更高级别的抽象,如工厂。这个类依赖于 B C的事实发出了一个明确的设计信息,即工厂之类的抽象可能会模糊不清。

答案 1 :(得分:1)

在我看来,在B和C实现相同界面的情况下,正确的方法是传递factory。此外,我会避免依赖具体类型,而是依赖于接口。如果您必须专门获取这些2或者为每个其他接口添加并依赖于该接口,或者去工厂。

有关更完整的示例,请参阅this question

public enum XTypes
{
    A,B,C...
}

public interface IXFactory
{
    IX GetX(XTypes xType);
}

public interface IX
{
    void SomeMethod()
}

//And I'd do A as an abstract class and rename to XBase
public class A : IX
{
    public void SomeMethod() {}
}

public class D
{
    public D(IXFactory xFactory)
    {
        XFactory = xFactory;
    }

    public void SomeMethod()
    {
        var x1 = XFactory.GetX(XTypes.A);
        var x2 = XFactory.GetX(XTypes.C);
    }

    public IXFactory XFactory { get; set; }
}

我个人不会在下列情况下出厂:

  1. 我只需要在程序的整个生命周期中使用特定的依赖项实现。
  2. 我需要该依赖项的所有实现并执行所有这些实现(仅依赖于IEnumerable<IDependency>
  3. 在整个代码中只有一个依赖项的实现(很容易添加一个工厂 - 所以有一天我可能需要,然后我会添加)
  4. 此外,让IX本身声明他的密钥(在本例中为enum)然后工厂的实现非常干净是很好的。

    同样 - 在Castle Windosr中(我确信在其他Ioc容器中也是如此),您可以通过实施{{1}来操纵TypedFactoryFacility然后你甚至不需要自己实施工厂。

    *如果代替ITypedFactoryComponentSelector您将拥有一个对象,则可以将enum更改为IX,然后IX<XRequestBase>将自动映射并运行:)