1

我有以下课程:

  类验证器 {
    私有最终 SchemaFetcher schemaFetcher;

    @注入
    验证器(SchemaFetcher schemaFetcher){...}
  }

  类 DatabaseSchemaFetcher 实现 SchemaFetcher {
     @覆盖
     Schema loadSchema(final SchemaDefinition schemaDef);

     @覆盖
     boolean compareSchemaWithSource(final SchemaDefinition schemaDef, final Schema updatedSchema);
  }

这只是其中一个示例,我还有一些其他类似的类,我将它们作为依赖项注入到其他类中。但它使我的 SchemaFetcher 类像一个单例,我不断地将 schemaDefinition 传递给它的每个方法。这似乎非常程序化,我实际上想让 SchemaDefinition 成为 DatabaseSchemaFetcher 类的实例变量,但在这种情况下,我将无法将 SchemaFetcher 对象注入到我的 Validator 类中,而我应该这样做

   验证(字符串模式名称){
     SchemaDefinition schemaDef = buildSchemaDefinitionFrom(schemaName);
     SchemaFetcher fetcher = new DatabaseSchemaFetcher(schemaDef);
   }

但这使我与 fetcher 紧密耦合,这就是我想首先使用依赖注入的原因。

我可以看到我可能有一个 DatabaseSchemaFetcher 的默认构造函数,然后是一个 setSchemaDefintion() 设置器来实现这一点,但这违反了完全使用构造函数构建对象的原则。

如何改进这一点,使其没有程序样式获取器,但也将我的依赖项注入构造函数?我更喜欢构造函数注入,因为它清楚地定义了我的依赖项,而无需任何人查看类的实现来找出类在我使用工厂或服务定位器时使用的依赖项。

4

3 回答 3

5

依赖注入是那些非常好的想法之一,它看起来非常好,以至于它被严重过度使用。我不会使用 DI 框架将 Fetcher 注入到验证器中。相反,我会让 DI 框架将工厂注入“main”。工厂使用适当的 SchemaDefinition 创建 Fetcher 并将其传递给 Validator。

请记住,我们想要一个将“main”与应用程序的其余部分分开的边界,并且所有依赖项都应该从“main”指向应用程序。应用程序不应该知道“main”。即“main”是应用程序的插件。

一般来说,应该使用 DI 注入到“main”中,然后 main 使用更传统的技术将工厂、策略或只是常规的旧抽象接口传递到应用程序中。

于 2012-07-01T18:24:21.093 回答
0

在这种情况下,我不确定彼此的用途Dependecy Injection和相互关系。Procedural

我认为真正的问题是您选择的对象建模方式并未反映既定目标。

在您提供的代码Validator中,我看不到任何用途。如果它的目的是验证SchemaFetcher对象,那么它可能不应该有超出验证规则的状态,然后接受任意SchemaFetcher对象进行验证。

至于DataBaseSchemaFetcher我再次难以理解这是做什么的。如果其声明的目的只是获取模式,那么它不需要关于DatabaseSchema对象的状态,因此应该接受DatabaseSchema它负责对DatabaseSchema. 任何内部状态都应该只与类的获取行为有关。

克服这些情况的一种尝试过且真正的方法painted in a corner是坐下来,非常努力地为每个班级分配一个单一的职责,并牢记以下几点:

  1. 关于您要解决的确切问题的领域真的很难。

  2. 不要解决任何你没有的问题。把你的可扩展性梦想扔掉。他们几乎总是错的,只会浪费大量时间。

  3. 接受您的设计必然有缺陷,您将不得不在以后更改它。

于 2012-07-01T18:40:51.660 回答
0

为什么说您在第二个解决方案中与 SchemaFetcher 紧密耦合?
您在那里提供了一个接口,因此您不会与任何特定的实现耦合,而只是与 SchemaFetcher 的定义(即 SchemaFetcher 的合同)耦合
您可以考虑拥有一个 Validator 类,该类将其 CTOR SchemaDefinition,并且您的 DatabaseSchemaFetcher 可以为其保存一个字段。这样,如果需要,您还可以扩展 Validator 类更改验证逻辑。
但是,如何传递模式定义对象的问题又一次出现了。不确定是否应该在此处使用注入 - 考虑更改您的设计。

于 2012-07-01T16:43:09.460 回答