Java接口的实现应该驻留在哪个包中?

Java接口的实现应该驻留在哪个包中?,java,interface,package,Java,Interface,Package,假设我有一个界面: package org.my.dicom.CEchoSCU; public interface CEchoSCU { // stuff here... } public class SimpleCEchoSCU implements CEchoSCU { // stuff here... } 我还将有一个接口的实现: package org.my.dicom.CEchoSCU; public interface CEchoSCU { // st

假设我有一个界面:

package org.my.dicom.CEchoSCU;

public interface CEchoSCU {
    // stuff here...
}
public class SimpleCEchoSCU implements CEchoSCU {
    // stuff here...
}
我还将有一个接口的实现:

package org.my.dicom.CEchoSCU;

public interface CEchoSCU {
    // stuff here...
}
public class SimpleCEchoSCU implements CEchoSCU {
    // stuff here...
}

我的问题是,哪一个方案应该包含实施?我见过其他开发人员将实现与接口放在同一个包中(
org.my.dicom
,在本例中),以及使用单独包的情况(通常类似于
org.my.dicom.impl
)。除了个人偏好之外,还有什么理由更喜欢其中一个吗?

我更喜欢将实现放在具有以下名称的包中:

path.to.package.of.interface.impl

然而,我不认为这是一个普遍的惯例,我想这是开发软件的组织所特有的。

包通常是偏好和组织的问题。有些地方会使用构建脚本过滤掉API接口,例如,如果它们在单独的实现包中,这可能更容易做到。实际上,我认为最主要的是保持一致性,这样人们就知道会发生什么(除非你使用的工具或脚本对你施加了限制)。

好吧,对于你将
实现
类和
接口放置在何处,这不是一条硬性规定。您可以将它们放在任何包中,只要它们可以在应该在的地方访问

但是,当然,您也希望将所有与
相关的类
放在一个
包中
,而与
类集
不相关的
则放在不同的包中

大多数时候,我的方法是: 我将我的
接口
保存在
不同的包中
,将
实现类
保存在
不同的包中
。这样,如果我想将我的接口提供给其他人,那么我可以直接提供包含所有接口的包

但是,这完全取决于您的需求,以及您在代码中遵循的设计实践

因此,我选择的包名通常是:-

  • 接口的
    com.someName.api
    ->
  • com.someName.impl
    ->用于实现类

这样,我就可以轻松地将我的
api
实现

分开,将实现类放在任何包中都没有错。这不会有任何遵从错误。但是,它取决于项目代码设置,将impl类放置在何处。在大多数情况下,实现类将与接口的实现类位于同一个包中

但是,接口可以由不同种类的类实现,因此在这种情况下,实现类和接口将位于不同的包中


例如,可以通过
果冻
甚至
汽车
实现界面
可弹跳

一个类实现了一个接口,以及其他功能。我会将该类粘贴在一个与该类的其余部分所做/包含的内容相关的包中,而不是一个反映其实现的一个接口的包中。例如,如果我有200个实现可打印的类,我不会将它们全部放在com.mycompany.impl.Printable包中。实现printable的飞机类将与其他飞机类放在一个包中。船上的课程会和其他船上的东西一起打包。实现Printable的Car类将与其他Car内容放在一个包中


如果所有SimpleCEchoSCU(和任何其他未来类)都实现了CEchoSCU,那么您应该考虑将CEchoSCU抽象为基类,并导出不同的实现。无论哪种方式,(接口或抽象基类)事物都是完全相关的,我会将它们放在同一个包中。

我通常遵循如下规则:

  • 如果您想提供通用实现,请将它们放在相同的位置 包(例如列表和阵列列表)
  • 如果您有可重用的实现,但例如针对不同的技术或不同的业务功能,请将它们放在单独的包中
  • 如果您有其他人不应该直接实例化的私有实现,请将它们放在*.impl或*.internal包中。这在OSGi捆绑包中非常常见

您可以将实现类放在包中的任何包“impl”中,而类则是不在命名约定上下功夫的标志。如此多的开发者认为这是一个可以接受的惯例,这是一个令人悲哀的状况。也可以把它称为“StaleCalk”,以表示它所传达的所有信息。在抽象类上不完全一致。同一个接口不是考虑抽象类的原因。抽象类意味着继承,继承意味着不止一个接口,意味着一级类型的祖先相同。如果你知道我的意思。鱼和鸟可能有相同的接口、移动、呼吸,但是我认为通过继承来做任何功能代码的重用是有风险的,它们是太远的不同类型。尽管您可能希望在实现代码重用时,它们的实现会有很大的差异。