java - 避免将依赖项“向下传递”到实体子类
问题描述
我有以下问题:
我有一个名为 的超类Entity
,它提供了每个实体都有的一些基本方法。为此,它需要一些服务才能运行,例如AbstractPotionService
. 它的任何子类都不需要这种依赖关系,但是每次实例化实体的子类型时我都必须传递它,例如MobileEntity
public class Entity {
private AbstractPotionService potionService;
protected EntityTypeConverter converter;
public Entity(EntityTypeConverter converter, AbstractPotionService potionService) {
this.converter = converter;
this.potionService = potionService;
}
public void addEffect(EffectType effectType, int durationInSeconds) {
potionservice.applyEffectTo(this, effectType, durationInSeconds);
}
...
}
public class MobileEntity extends Entity {
public MobileEntity(EntityTypeConverter converter, AbstractPotionService potionService){
super(converter, potionService);
}
public attack(MobileEntity victim) {
...
}
...
}
这感觉有点不对劲,因为它是很多乏味的工作,并且当我想扩展Entity
类时会使项目的可维护性降低。我的第一个想法是在这里使用单例并Entity
直接(通过静态方法)在构造函数中获取服务的实例,但这不会创建上帝依赖吗?
我还阅读了关于作文的文章,但我找不到一个合适的例子来说明如何在我的案例中应用它。有人有想法吗?
解决方案
依赖注入原则、实践和模式(DIPP&P)(我合着)的第 4 章(第 106 页)指出:
除了通常的数据成员集之外,还包含行为的实体将很容易获得各种方法,每个方法都需要它们自己的依赖项。尽管您可能很想使用构造函数注入来注入此类依赖项,但这会导致需要创建每个此类实体及其所有依赖项的情况,即使对于给定的用例可能只需要少数几个。这使测试实体的逻辑变得复杂,因为所有依赖项都需要提供给构造函数,即使测试可能只对少数依赖项感兴趣。Method Injection [...] 提供了一个更好的选择。
在您的情况下,所需的构造函数依赖项的情况甚至被夸大了,因为每个子类型都需要在自己的构造函数中具有这些依赖项,并且需要将它们传递给Entity
基类型。如果您向其添加新的依赖项,Entity
将导致所有派生实体发生更改(以及它们的所有测试),这可能会导致可维护性问题。
因此,DIPP&P 建议改用方法注入,在您的情况下,它看起来像这样:
public class Entity {
public Entity() { } // <-- No more Constructor Injection
public void addEffect(
EffectType effectType,
int durationInSeconds,
AbstractPotionService potionService) // <-- Method Injection
{
potionservice.applyEffectTo(this, effectType, durationInSeconds);
}
...
}
使用方法注入,需要依赖项的方法随该依赖项一起提供。虽然该方法使用依赖项,但与构造函数注入不同,它不存储依赖项。
这意味着它现在是消费者提供正确依赖关系的责任。在大多数情况下,这意味着使用Constructor Injection将依赖项注入消费者。
推荐阅读
- google-sheets - 两列单元格列表(下拉列表) - Google 表格
- node.js - mongoose Schema 中的验证
- python - 基于单词匹配与python分割文本
- ruby-on-rails - 模型关联问题:NoMethodError: undefined method `extensions' for #
- python - 属性方法中的 Setter 方法
- java - 如何在 Android Studio 中启用按钮
- python - 使用python从字符串中提取版本?
- python - 无法使用发布请求解析某些搜索结果中的表格内容
- python - 如果我反转 Conv1D 的输入形状会发生什么?
- python - 从 python2 调用 python3 方法