ES6类构造函数参数超过require

问题描述 投票:0回答:4

使用ES6类时,为什么不通过构造函数传递依赖项,而不是在顶部将它们列为import / require:例如

class DEF {
  constructor(ABC) {
    this.abc = new ABC();
  }
}

代替

const ABC = require('./abc');

class DEF {
  constructor() {
    this.abc = new ABC();
  }
}

我试图理解这些编程风格和两者的含义之间的区别?

javascript ecmascript-6 es6-class
4个回答
2
投票

这是Dependency Injection的一种形式,可能在各种情况下都有用。例如用于测试。

通常你做的事情就像

const DefaultABC = require('./abc');

class DEF {
  constructor(ABC = DefaultABC) {
    this.abc = new ABC();
  }
}

然后在测试文件中提供自定义ABC实现。这可能比模拟模块或以其他方式劫持模块分辨率和加载更简单。


0
投票

因为有时候传递不同的类是有意义的:

new Vehicle(/*for*/ Animal)
new Vehicle(/*for*/ Human)

0
投票

在第一个示例中,您可以使用不同版本的ABC,只要它们实现相同的接口即可。这提供了比后者更松散的耦合,其缺点是您需要完全了解DEF将如何在内部使用ABC来确保接口匹配。

在第二个示例中,您不必担心使用哪个版本的ABC。这两个类现在彼此紧密耦合,其优点是只需知道DEF如何工作,不需要ABC知识。

因此,两种“风格”解决了不同的问题。

当我希望能够将不同的可选组件“插入”DEF时,我会使用第一种风格。但是当我扩展课程时,我会使用第二种风格。


0
投票

这非常依赖于用例。这里的问题是决策在哪里?

如果你的类的工作决定使用哪个原型方法来实例化一个新对象?或者您是否希望调用者决定使用哪种原型方法?在设计应用程序时应该询问和思考这些问题,并根据设计分歧来分配责任。

举个简单的补充:

1 + 1 //=> 2
1 + '1' //=> '11'

在上述情况下,决策制定在内部。我不能提供返回的对象类型。我唯一的责任是提供正确的对象。你可以用一个虚构的变体来衡量它:

1.add(1, Number) //=> 2
1.add('1', Number) //=> 2
1.add(1, String) //=> '11'

这两者都不对或错。

© www.soinside.com 2019 - 2024. All rights reserved.