我正在开发一种从语言A到B的翻译器(是的,它有点像编译器)。翻译通常来自几个不同的文件,每个文件都有相同的3个部分进行翻译。所以,我这样做的方式,我有以下方式:
当我实例化一个翻译并给它一些数据时,它需要生成所有需要的FileTranslator类。由于我不应该在译者中new
,我应该从上面要求一家工厂。 Sections译员也是如此。这就产生了一个问题,即我不得不创建许多样板工厂。此外,每个翻译人员可能需要更多的工厂来生成他们可能想要使用的其他类。
我认为这是错误的方式还是只是它的方式?我不允许在这个项目中使用任何类型的DI / IoC框架,顺便说一句。
我担心我的消息不会被发送。
在这种特殊情况下,由于我的Translator类需要能够随时生成一些FileTranslator,因此需要FileTranslatorFactory。我知道我可以让一个IoC容器为我做接线,但IoC容器本身不会因为必须编写FileTranslatorFactory本身代码的问题而省去我。我是对的吗?
现在,问题是FileTranslator还必须能够在需要SectionATranslators,SectionBTranslators和SectionCTranslators时生成(并且不认为它们是相似的,因为它们的名字是 - 它们完全不同而且没有任何内容互相帮助!)。所以我必须为每一个定义工厂。所以对于这样一个简单的5类系统,我需要创建4个(!!!)工厂。
因为我不希望我的域对象依赖于IoC-Container而且我不想为所有似乎需要的4种对象都有一个工厂,我仍然缺少某些东西?
答案 0 :(得分:6)
这样的类层次结构的手动DI中涉及很多样板代码的事实是为什么框架存在。对不起,除非你能得到没有DI / IoC框架规则决定改变主意的人,否则你要写的是很多样板代码,否则你最终会自己编写一个框架。
编辑 - 使用一个完全虚构的框架,尽可能保持这种不可知性,但解释如何在许多情况下消除除容器之外的所有调用。
因此,Translator
的实现方式如下:
public class Translator
{
private ITranslator translatorInstance;
public Translator()
{
SomeContainer container = SomeContainer.CreateFromConfig(configFilePath);
// this is the ONLY point we touch the container
translatorInstance = container.GetMeA<ITranslator>();
}
// implementation
}
我们可以看到它作为工厂工作,并且是唯一需要了解容器本身的类。因此,ITranslator
的一个具体实现者的实现可以是:
public class FileTranslator : ITranslator
{
// private fields
public FileTranslator( ISectionATranslator sectionAtrans,
ISectionBTranslator sectionBtrans,
ISectionCTranslator sectionCtrans)
{
this.sectionAtrans = sectionAtrans;
// etc
}
// implementation
}
请注意FileTranslator
对于哪些具体类实际实现它所依赖的接口一无所知,也不需要任何类型的工厂。事实上,容器会为你做这件事。容器可以通过多种方式处理这些问题,其中一个例子是显式配置,例如:
<!-- absolutely fictitious configuration file, but similar to many frameworks -->
<ContainerConfig>
<ObjectResolver interface="ITranslator">
<ConcreteType type="FileTranslator">
<ConstructorInjection>
<Argument ordinal="0" type="SectionATranslator" />
<Argument ordinal="1" type="SectionBTranslator" />
<Argument ordinal="2" type="SectionCTranslator" />
</ConstructorInjection>
</ConcreteType>
</ObjectResolver>
</ContainerConfig>
许多框架甚至不需要您定义特定的构造函数参数,您可以只声明如果您想要ISectionATranslator
然后返回SectionATranslator
并且它会在调用构造函数之前自动创建这些参数
另请注意,某些框架提供了使用流畅样式API在代码中定义这些类型解析规则的选项,有些框架允许您通过某个名称定义多种可能的解析特定类型的方法(可能是{{1}实现与"Production"
实现相比)。
请注意,我一直保持上述故意模糊,因为我不想说哪个框架最好(并且说实话,我认为这取决于您的个人需求) - 在StackOverflow上的其他地方检查框架比较,并请尝试一些(也许你可以尝试一些而不告诉你的老板!)。但是,希望上面说明为什么IoC容器可以通过消除工厂类层上的层的需要来使代码更加清晰。