ES6类和类实例作为构造函数的参数

4
类A需要类B的实例。我应该在A的构造函数中创建B实例,还是在初始化类A时创建实例并将实例传递给A构造函数?
计划A:
class A { constructor() { this.b = new B(); } }

备选方案:

const b = new B();

class A() { 
    constructor(b) { 
        this.b = b; 
    }
}

const a = new A(b);

理想情况下,如果类A需要类B的实例,则应在内部创建它。消费类A的代码不需要知道类需要什么依赖项。 - Terry
我会选择计划B,因为它对于管理依赖注入非常有用。 - Ankit Agarwal
计划B非常有帮助。 - Jasmin Mistry
正如所说,这只是一个观点问题。这取决于这些类将如何使用。例如,调用A的人是否有必要传入除B以外的任何东西?他们是否需要与B交互? - Mark
这个问题实际上无法得到恰当的回答,因为您询问的事项取决于整个情境。 - Marty
所以,请您提供不同上下文和场景的示例。 - user3462947
4个回答

2
第一种策略适用于两个类存在相互关系,如果它们的确切形式没有彼此,而子实例没有任何特殊特征使得手动提供它们没有任何好处,则这种策略是合适的。
后一种注入依赖项的策略更加灵活。在类型化的语言中,这更加明显,您可以清楚地定义类抽象或接口来描述对象的“外观”,而不是实际实现,例如使用TypeScript:
class Process {
  private storage: StorageInterface;

  constructor(storage: StorageInterface) {
    this.storage = storage;
  }
}

interface StorageInterface {
  store(data: any): Promise<void>;
}

很明显,这里的Process需要一个提供store函数的实例,但它并不关心实际实现是什么样子的 - 这取决于实现StorageInterface的类:

class PostgresStorage implements StorageInterface {
  public async store(data: any): Promise<void> {
    // do some postgres query
  }
}

class FilesystemStorage implements StorageInterface {
  public async store(data: any): Promise<void> {
    // store in the filesystem
  }
}

现在,我们可以完全灵活地选择一个Process实例所要使用的“存储”类型,而不是它本身管理其能够使用的存储。这意味着我们可以创建无限种存储类型,而无需修改代码库的其余部分,并且更清晰地了解Process正在与哪些内容进行交互。
// A process that stores something in a Postgres instance.
const processA: Process = new Process(new PostgresStorage());

// A process that stores something on the filesystem.
const processB: Process = new Process(new FilesystemStorage());

1
你的备选方案绝对是更好的选择,因为它使你的 A 类 更加灵活,并消除了对 B 类 工作方式的依赖。

1

如果

  • 类B在未来不会被类C替换

  • 类B不使用任何外部依赖,如ajax、数据库或其他东西。

或者

  • 您的应用程序是概念验证或您真的时间很紧

那么计划A是可行的。

它将为您带来灵活性,使您能够随时更改A类的行为,提供更多的通用性,并通过模拟此依赖项来帮助测试。

所以我会说计划A是关于简单性的,计划B是关于灵活性和测试的。在每个当前情况下选择您需要的内容。

希望这可以帮助您。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接