阅读后包装名称应为单数还是复数?在我看来,我从未见过涉及我的宠儿之一的适当辩论:命名接口的实现。
假设您有一个Order
旨在以各种方式实现的接口,但是在首次创建项目时只有初始实现。您是否选择DefaultOrder
或OrderImpl
或采取其他措施来避免错误的二分法?当出现更多实现时,您会怎么做?
最重要的是...为什么?
阅读后包装名称应为单数还是复数?在我看来,我从未见过涉及我的宠儿之一的适当辩论:命名接口的实现。
假设您有一个Order
旨在以各种方式实现的接口,但是在首次创建项目时只有初始实现。您是否选择DefaultOrder
或OrderImpl
或采取其他措施来避免错误的二分法?当出现更多实现时,您会怎么做?
最重要的是...为什么?
Answers:
名称有机会传达含义。您为什么要放弃Impl的机会?
首先,如果您只有一个实现,则取消该接口。 它会创建此命名问题,并且不添加任何内容。更糟糕的是,如果您和所有其他开发人员不注意始终仅使用接口,则可能导致API中的方法签名不一致。
鉴于此,我们可以假定每个接口都有或可能有两个或更多的实现。
如果您现在只有一个,并且您不知道另一个可能会有所不同,那么Default是一个不错的开始。
如果您现在有两个,请根据其用途分别命名。
示例:最近,我们有一个具体的Context类(参考数据库)。已经认识到,我们需要能够表示一个脱机的上下文,因此名称Context被用于新接口(以保持与旧API的兼容性),并且创建了一个新的实现OfflineContext。但是猜猜原来的名字改成了什么吗?没错,ContextImpl(喜欢)。
在这种情况下,DefaultContext可能还可以,人们会理解它,但它的描述性不如可能。毕竟,如果它不离线,那是什么?所以我们选择了:OnlineContext。
特殊情况: 在接口上使用“ I”前缀
建议在接口上使用I前缀作为其他答案之一。最好,你没有需要做到这一点。
但是,如果您既需要一个接口来进行自定义实现,又要使用一个主要的具体实现,并且其基本名称过于简单以至于不能仅放弃一个接口,那么可以考虑添加界面上的“我”(不过,如果它仍然不适合您和您的团队,则完全可以)。
示例:许多对象可以是“ EventDispatcher”。为了使用API,它必须符合接口。但是,您还希望提供一个用于委派的基本事件分发程序。 DefaultEventDispatcher可以,但是有点长,如果经常要看到它的名称,您可能更喜欢为具体类使用基本名称EventDispatcher,并为自定义实现实现IEventDispatcher:
/* Option 1, traditional verbose naming: */
interface EventDispatcher { /* interface for all event dispatchers */ }
class DefaultEventDispatcher implements EventDispatcher {
/* default event dispatcher */
}
/* Option 2, "I" abbreviation because "EventDispatcher" will be a common default: */
interface IEventDispatcher { /* interface for all event dispatchers */ }
class EventDispatcher implements IEventDispatcher {
/* default event dispatcher. */
}
if you will only ever have one implementation, do away with the interface
-除非您要测试组件,否则您可能需要保留该接口以便创建MockOrder,OrderStub或类似组件。
我同意Nicole的回答(特别是在大多数情况下可能不需要该接口),但是为了讨论起见,我将抛出除OrderImpl
和之外的其他替代方案DefaultOrder
:将实现隐藏在静态工厂方法(如)之后Orders.create()
。例如:
public final class Orders {
public static Order create() {
return new Order() {
// Implementation goes here.
};
}
}
使用这种方法,实现可以是匿名内部类,也可以是名称中带有Default
或Impl
名称的私有类,或者可以完全命名为其他名称。无论选择哪个选项,呼叫者都不必在意,因此无论现在还是以后决定更改时,您都可以获得更大的灵活性。
在实践中,这种模式的一些很好的例子是java.util.Collections
and java.util.concurrent.Executors
实用程序类,其方法返回隐藏的实现。正如有效的Java在项目1中提到的那样,此模式可以帮助使API的“概念权重”保持较小。
您可以使用前缀I(IWhatever)命名接口,然后实现实现。
正式的Java代码约定没有说明接口的这种命名方式,但是这种命名方式有助于识别和导航。