1

我正在实现类似于 nand2tetris 项目的东西,除了我用 java 编写所有代码而不使用 HDL 并且我自己编写测试。对于问题说明:我已经实现了与 OR、AND、XOR 和 NOT 逻辑门相关的 nand 逻辑门。

我对这两种方法有疑问:

1) 直接投资方法

public interface Nand {
  int nand(int a, int b);
}

public class NandImpl implements Nand {
  public int nand(int a, int b) {
    return a * b == 0 ? 1 : 0;
  }
}

public interface And {
  int and(int a, int b);
}

public class AndImpl implements And {
  Nand nand;

  public AndImpl(Nand nand) {
    this.nand = nand;
  }

  public int and(int a, int b) {
    return nand.nand(nand.nand(a, b), nand.nand(a, b));
  }
}

2) 没有 DI 的方法

public class NandImpl {

  static NandImpl singleton = null;

  protected NandImpl() {
  }

  public static NandImpl getInstance() {
    if(singleton == null) {
      singleton = new NandImpl();
    }
    return singleton;
  }

  public int nand(int a, int b) {
    return a * b == 0 ? 1 : 0;
  }
}

public class AndImpl {

  static AndImpl singleton = null;
  NandImpl nand;

  protected AndImpl() {
    nand = NandImpl.getInstance();
  }

  public static AndImpl getInstance() {
    if(singleton == null) {
      singleton = new AndImpl();
    }
    return singleton;
  }

  public int and(int a, int b) {
    return nand.nand(nand.nand(a, b), nand.nand(a, b));
  }
}

我从 1) 下的方法开始,但我现在有疑问,因为我总是需要在测试中存根依赖项才能获得真正的实现,这对我来说似乎是错误的。此外,我在这里看不到 DI 的任何优势,因为我可以使用真值表完全测试 AND、OR、NOT 和 XOR 实现。

我应该选择哪种方式?

4

1 回答 1

3

想想你如何使用一个实际的逻辑门。

您通常有两个输入、一个输出和一个黑匣子。无论是 NAND、AND、OR 还是其他任何东西都没有关系——界面看起来是一样的。所有逻辑门看起来都一样。如果您有一个采用不同逻辑门的电路,您可以将其中任何一个插入其中并获得不同的行为。

因此,您的接口命名是问题的一部分。这不是具有实现的 NAND 或 AND,它是可以实现为 NAND 或 AND 的 LogicGate。

如果你这样做,很明显与门不能仅仅依赖于传递给它的任何东西的实现。它需要实际的与非门,或其他使其工作的方式。

当使用其协作者的事物可以完全信任它们并且不需要了解它们的实现时,DI 是合适的。这里不是这种情况——可能还有其他方法可以让与门工作——所以不要使用 DI。

如果有什么东西使用逻辑门而不关心它的实现——只要相信它正在做适当的工作,无论当时发生了什么——那么你可以使用 DI。

于 2013-06-02T11:55:29.020 回答