4

几年以来,常识似乎表明最好针对接口进行编程而不是针对实现进行编程。对于高级代码,这确实看起来合乎逻辑,例如,如果我的应用程序中有一个复杂的求解器,最好有这样的东西:

ISolver *solver = solverFactory.getSolver();
solver->solve(inputdata);

而不是

Solver solver;
solver.solve(inputdata);

在第一个代码中,模拟求解器也更容易,因此也更容易进行单元测试。

但我的问题是:在哪个级别使用界面不再有意义。例如,如果我的应用程序中有一个 ComplexNumber 类(或 String 类,或其他),则编写以下代码:

IComplexNumber *complexNumber = complexNumberFactory.create(1,2);   // 1+2i

似乎比写作复杂得多(尤其是在性能方面):

ComplexNumber complexNumber(1,2);   // 1+2i

那么,哪些元素在决定是否应该将某些东西放在接口后面以及什么时候不应该放在接口后面时很重要?

4

3 回答 3

3

迁移到接口的原因是当它使事情变得更简单或减少耦合时。(这就是接口的用途)。

离开界面的原因是它是否会使事情变得更复杂或降低性能(但可以肯定的是)。我认为你的 IComplexNumber 类实际上使类层次结构更加复杂,除非你引入一个 MockComplexNumber,但我怀疑这样一个类是否有用......它可能会使事情变慢,但我会衡量.

但是不要认为你需要以一种方式做所有事情,或者你的决定是一成不变的。使用界面转换/转换非常容易。

于 2010-09-27T10:21:30.320 回答
1

如果根据它们所扮演的角色将类分为“服务”类和“价值”类,那么答案很简单。仅在服务类上使用接口。在您的问题中,“求解器”是一项服务,而“复数”是一个值。

值类应该很容易使用 new() 创建,因为它们只接受构造函数中的基本类型和其他值类。值类对模拟没有用,因为您可以使用真实的东西。

模拟服务类可能很有用,您可能需要多个实现。您的solverFactory 可以返回一个naiveSolver、一个lookupSolver、一个geneticSolver、一个mockSolver 等。这里的接口是有用的。

于 2010-09-28T22:49:56.360 回答
-2

对于 C++,这无关紧要,因为 C++ 具有多重继承,因此接口是一个抽象类,您可以添加实现。我发现最常用的接口是 Java 和 C#,它们具有单一继承,如果你想让一个类实现几件事,只有一个可以是抽象类,其他的必须是接口

于 2010-09-27T10:23:10.397 回答