4

假设 A、B、C 派生自 AbstractBaseClass 并且它们都是同一个 java 项目的一部分,它们的包结构形式...

 package com.whatever.###
 AbstractBaseClass.java

 package com.whatever.###.###
 A.java
 B.java
 C.java

...通常比以下形式的包装结构更受欢迎...

 package com.whatever.###.###
 AbstractBaseClass.java
 A.java
 B.java
 C.java

?

...或者很少有人可能关心?

4

5 回答 5

1

我编写了一个相当复杂的应用程序应用程序,它使用了第一个示例,这就是我如何证明设计的合理性。在我的案例中,有一个与承保案例定价相关的通用界面,但有几个供应商可以提供不同的 Web 服务来填充实际数据。这是包结构

com.example.pricing
 \IPricingProvider.java
 \AbstractPriceProvider.java
com.example.pricing.vendorA
   \PricingEngine.java
com.example.pricing.vendorB
   \PricingEngine.java
com.example.pricing.vendorC
   \PricingEngine.java

然后在我的代码中,我使用import来连接我想要的引擎。像这样:

import com.example.pricing.*;
import com.example.pricing.vendorB.*;

IPricingProvider provider = Engine.create();

对我来说,优势是能够为每个供应商提供复杂而混乱的实现(两个是基于 rest 的,一个是使用 Web 服务,wsimport因此生成了很多 Java 文件),并且不会让 Eclipse 自动完成看起来像一场噩梦。此外,它还使将单个供应商移交给不同的开发人员变得更加容易。

于 2013-02-07T18:15:09.143 回答
0

令人惊讶的是,答案是。这取决于。

如果你打算做两个兄弟后代,那么每个(如三个)一个文件是有意义的。如果它们很小并且/或者您几乎总是同时使用它们(例如目录和文件),那么无论如何都要将它们全部合二为一,这是一个务实的论据。

如果您正在构建一些深层继承层次结构,其中只有最终后代具有可用功能(类越抽象,它做的越少),那么将它放在单独的文件中是没有意义的。

于 2013-02-07T18:24:52.863 回答
0

这实际上是一种很好的做法。太多的包会很快变得混乱。将实现类保存在同一个包中可以避免额外的导入语句,并且可以在应用程序代码库增长时轻松找到抽象类。例外情况是,您有更大的实现类组,这些实现类都从抽象类扩展而来。因此,例如,如果您有一个 MySQL 实现和一个 Mongo 实现的多个抽象类,您可能希望将它们放在单独的子包中。就像是

com.foo.data  <--- abstract classes
com.foo.data.mysql  <-- impl
com.foo.data.mongo  <-- impl
于 2013-02-07T18:20:28.903 回答
0

包结构有两个有时是不一致的目的。

  1. 让学习您的 API 和代码的人更容易找到满足他们需求的类。在这种情况下,您希望将类似的东西组合在一起,并使用包名称,让浏览 Javadoc 的人可以清楚地看到在哪里查找。这主张使用对 API 客户端有意义的具有广泛划分的少量软件包。
  2. 允许类访问彼此的包私有 API。这证明了许多紧密耦合类的小组。

像包这样的大规模组织不应该依赖于当前的实现细节,所以我更喜欢(1)而不是(2)。

深层层次结构很难学习,所以如果添加名称元素不能使学习 API 变得更容易,也不能帮助人们过滤掉与他们当前任务无关的部分,那么就把它排除在外。

于 2013-02-07T18:20:51.327 回答
0

我认为这取决于哪个部分对客户更重要:超类还是子类?

当您首先考虑子类并将一些公共部分重构为超类时,通常会出现后者。那么这个超类应该在同一个包中,并且不公开可见,就像路易斯在他的评论中所说的那样。如果客户需要查看子类的类型,那么您倾向于使用这种模式。

但是,当您从实现中抽象出来并且客户端通常只使用 Jason 的回答中的超类时,那么您应该遵循将每个子类放入其自己的包中的策略。通常这些子类需要更多与外部代码无关的类,因此为它们提供自己的包是一件好事。

于 2013-02-07T18:22:12.603 回答