简单工厂和 IOC
Simple factory and IOC
我有一个 class A{}
class B:A{}
class C:A{}
和 class D{}
D 有需要使用 B 的方法和需要使用 C
.
的方法
将来我可能会有更多 class 继承自 A
的 D
需要使用
应该D
有一个像这样的构造函数:
public D(B b, C c)
或者 A
应该得到一个简单的工厂 (F)
它将 return
正确 class。然后构造函数将是 public D(F f)
F
将有一个 CreateInstance
方法来获取枚举和 return 正确的类型。
完全注入会将所有内容保留在组合根中。
简单工厂将简化构造函数。
在我看来,在 B 和 C 实现相同接口的情况下,正确的做法是传递一个 factory
。此外,我会避免依赖于具体类型,而是依赖于接口。如果您必须专门获取这 2 个,那么或者为每个其他接口添加并依赖于该接口,或者去工厂。
(有关更完整的示例,请参阅 )
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; }
}
我个人不会在以下情况下放置工厂:
- 在程序的整个生命周期中,我只需要一个特定的依赖实现。
- 我需要该依赖项的所有实现并执行所有这些(仅取决于
IEnumerable<IDependency>
- 在整个代码中只有一个依赖项的实现(添加工厂很容易 - 所以当有一天我可能需要时我会添加)
此外,让 IX
本身声明他的密钥(在本例中为 enum
)是很好的,然后工厂的实现非常干净。
Also - 在 Castle Windosr
中(我确信在其他 Ioc 容器中也是如此)有一个 TypedFactoryFacility
可以通过实现来操作a ITypedFactoryComponentSelector
然后你甚至不需要自己实现工厂。
*如果您将拥有一个对象而不是 enum
,您可以将 IX
更改为 IX<XRequestBase>
,然后 TypedFactoryFacility
将自动映射和工作:)
这里需要注意的问题是通过工厂方法引入不透明的依赖。
此时,D 依赖于 B 和 C。使用像这样的构造函数:
public D(B b, C c)
{
}
使依赖关系透明化。 IE。很清楚这个 class 需要做什么,这些东西可以直接提供。此外,自动化测试更容易一些,因为您可以直接提供假货,而无需提供提供其他假货的假货工厂。
使用工厂降低了这种清晰度,但确实增加了便利性,并且通过减少必须传入的依赖项的数量在一定程度上面向未来。
就我个人而言,我会坚持直接提供依赖项,直到构造函数签名变得笨拙或明确需要更高级别的抽象(如工厂)为止。 class 依赖于 both B
and C
的事实给出了一个明确的设计信息像工厂这样的抽象可能会模糊不清。
我有一个 class A{}
class B:A{}
class C:A{}
和 class D{}
D 有需要使用 B 的方法和需要使用 C
.
将来我可能会有更多 class 继承自 A
的 D
需要使用
应该D
有一个像这样的构造函数:
public
D(B b, C c)
或者
A
应该得到一个简单的工厂(F)
它将 return 正确 class。然后构造函数将是public D(F f)
F
将有一个 CreateInstance
方法来获取枚举和 return 正确的类型。
完全注入会将所有内容保留在组合根中。 简单工厂将简化构造函数。
在我看来,在 B 和 C 实现相同接口的情况下,正确的做法是传递一个 factory
。此外,我会避免依赖于具体类型,而是依赖于接口。如果您必须专门获取这 2 个,那么或者为每个其他接口添加并依赖于该接口,或者去工厂。
(有关更完整的示例,请参阅
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; }
}
我个人不会在以下情况下放置工厂:
- 在程序的整个生命周期中,我只需要一个特定的依赖实现。
- 我需要该依赖项的所有实现并执行所有这些(仅取决于
IEnumerable<IDependency>
- 在整个代码中只有一个依赖项的实现(添加工厂很容易 - 所以当有一天我可能需要时我会添加)
此外,让 IX
本身声明他的密钥(在本例中为 enum
)是很好的,然后工厂的实现非常干净。
Also - 在 Castle Windosr
中(我确信在其他 Ioc 容器中也是如此)有一个 TypedFactoryFacility
可以通过实现来操作a ITypedFactoryComponentSelector
然后你甚至不需要自己实现工厂。
*如果您将拥有一个对象而不是 enum
,您可以将 IX
更改为 IX<XRequestBase>
,然后 TypedFactoryFacility
将自动映射和工作:)
这里需要注意的问题是通过工厂方法引入不透明的依赖。
此时,D 依赖于 B 和 C。使用像这样的构造函数:
public D(B b, C c)
{
}
使依赖关系透明化。 IE。很清楚这个 class 需要做什么,这些东西可以直接提供。此外,自动化测试更容易一些,因为您可以直接提供假货,而无需提供提供其他假货的假货工厂。
使用工厂降低了这种清晰度,但确实增加了便利性,并且通过减少必须传入的依赖项的数量在一定程度上面向未来。
就我个人而言,我会坚持直接提供依赖项,直到构造函数签名变得笨拙或明确需要更高级别的抽象(如工厂)为止。 class 依赖于 both B
and C
的事实给出了一个明确的设计信息像工厂这样的抽象可能会模糊不清。