我有以下课程:
class Validator { private final SchemaFetcher schemaFetcher; @Inject Validator(SchemaFetcher schemaFetcher) {...} } class DatabaseSchemaFetcher implements SchemaFetcher { @Override Schema loadSchema(final SchemaDefinition schemaDef); @Override boolean compareSchemaWithSource(final SchemaDefinition schemaDef, final Schema updatedSchema); }
这只是其中一个例子,我有一些像这样的其他类,我作为依赖注入其他类。但它使我的SchemaFetcher类像一个单例,我不断将schemaDefinition传递给它的每个方法。这看起来非常程序化,我想让SchemaDefinition成为DatabaseSchemaFetcher类的一个实例变量,但在这种情况下,我无法将一个SchemaFetcher对象注入到我的Validator类中,而是我应该这样做
validate(String schemaName) { SchemaDefinition schemaDef = buildSchemaDefinitionFrom(schemaName); SchemaFetcher fetcher = new DatabaseSchemaFetcher(schemaDef); }
但是这使我与fetcher紧密耦合,这就是为什么我想首先使用依赖注入。
我可以看到我可能有一个DatabaseSchemaFetcher的默认构造函数,然后是一个setSchemaDefintion()setter来实现这个,但这违反了使用构造函数完全构建对象的原则。
如何改进这个以便没有程序样式的提取器,而且还将我的依赖项注入构造函数?我更喜欢构造函数注入,因为它清楚地定义了我的依赖关系,而没有任何人研究类的实现,以找出类在我使用工厂或服务定位器时使用的依赖项。
答案 0 :(得分:5)
依赖注入是一个非常好的想法,它看起来非常好,以至于它被严重过度使用。我不会使用DI框架将Fetcher注入Validator。相反,我有DI框架将工厂注入“main”。工厂使用适当的SchemaDefinition创建Fetcher并将其传递给Validator。
请记住,我们需要一个边界将“main”与应用程序的其余部分分开,并且所有依赖项都应该从“main”指向应用程序。应用程序不应该知道“主要”。即“main”是应用程序的插件。
通常,DI应该用于注入“main”,然后main使用更传统的技术将工厂,策略或常规的旧抽象接口传递到应用程序中。
答案 1 :(得分:0)
为什么你说在你的第二个解决方案中你与SchemaFetcher紧密耦合?
您提供了一个接口,因此您不会与任何特定的实现相关联,而只是与SchemaFetcher的定义(即SchemaFetcher的合同)相关联。
你可以考虑使用一个Validator类,它将CTOR接收到SchemaDefinition,你的DatabaseSchemaFetcher可以为它保存一个字段。这样,您还可以扩展Validator类,如果需要,可以更改验证逻辑。
但是,再一次,如何传递模式定义对象的问题也随之增加。不确定注射应该在这里使用 - 考虑改变你的设计。
答案 2 :(得分:0)
我不确定Dependecy Injection
和Procedural
在这种情况下对彼此的使用有何关系。
我认为真正的问题是你选择模仿对象的方式并不能反映出既定的目标。
在您提供的代码中Validator
没有任何目的,我可以看到。如果它的目的是验证SchemaFetcher
个对象,那么它可能没有超出验证规则的状态,然后接受仲裁SchemaFetcher
对象进行验证。
至于DataBaseSchemaFetcher
我再次努力去了解这是做什么的。如果其声明的目的仅仅是获取模式,则它不需要DatabaseSchema
个对象的状态,因此对于DatabaseSchema
采取行动的方法应该接受DatabaseSchema
。任何内部状态只应与类的提取行为相关。
过去这些painted in a corner
情况的一种经过验真的方法是坐下来,努力为每个班级分配一个责任,并牢记以下内容:
你想要解决的确切问题的领域真的很难。
不要解决任何你没有的问题。把你的可扩展性的梦想扔掉。他们几乎总是错的,只会是一个巨大的时间下沉。
接受您的设计必然缺陷,您必须稍后更改。