【问题标题】:Should my internal API classes be all in one package?我的内部 API 类应该都在一个包中吗?
【发布时间】:2011-02-25 10:10:49
【问题描述】:

我正在努力打包一个供公众使用的 API。因此,我试图限制只向那些我希望公开和可支持的方法公开。当然,在这之下还有许多有限的访问方法。

问题是我有很多内部代码需要访问这些受限制的方法,而不会将这些方法公开。这会产生两个问题:

  • 我无法创建接口 像这样在类之间进行通信 将使这些成为我的内部方法 公开。
  • 我无法访问受保护或默认 方法,除非我把大部分 我的内部课程在同一 包。

所以,我在完全隔离的包中有大约 70 或 80 个内部类,但访问修饰符过于宽松。你会说单个包是两害相权取其轻,还是有更好的方法来掩盖我的内部方法,同时保持更细化的包?

我很想在这里找到最佳实践。

我已经知道This

【问题讨论】:

  • 我认为这个问题有点主观:我个人不喜欢导致内部组织不佳的设计决策,例如您的所有类合一包装案例。但是现在还没有想到做这些事情的正确方法。

标签: java api


【解决方案1】:

您的问题有两种解决方案,它们不涉及将所有类保存在同一个包中。

第一种是使用(Practical API Design, Tulach 2008)中描述的 Friend Accessor/Friend Package 模式。

第二个是使用OSGi。有一篇文章here 解释了 OSGi 是如何做到这一点的。

相关问题:1234

【讨论】:

  • 这是一个很好的答案,朋友包的链接正是我正在寻找的解决方案。
  • 很高兴能帮上忙。我也需要解决这个看似严重的 Java 限制。这种模式应该是使用 Jetbrains MPS 或其他模型驱动开发工具扩展 Java 的理想选择。
  • 好吧,您仍然必须公开内部抽象访问器(因此是 API 的一部分)。更糟糕的是,一个邪恶的用户可以提供他/她自己的 AccessorImpl,从而迫使您的内部包使用他/她自己的 API。这将一直有效,直到 Item 类被初始化并触发 IllegalStateException。
【解决方案2】:

一个例子可能是Servlet API,正如您所见,它们已将通用 servlet API 和 http 分成两个包。

如果您将代码分隔在api.jarimplementation.jar 中,您可以使用对 api.jar 的用户不可见的接口来实现。 如果类的对象无论其封装如何,都必须以任何方式进行协作,那么方法当然必须是可见的(至少在实现中)。

【讨论】:

  • +1 感谢您提供信息。我知道我可以将问题打包,但我真的希望限制同时拥有 api 和实现 jar 的用户能够以非预期的方式访问非接口实现方法。
【解决方案3】:

是的,你只是不能保护内部实现的东西不被访问。有一些技术(如 OSGi)在运行时/应用程序启动期间提供解决方案。这是一个 java 语言设计的模块化缺陷(但由于向下兼容性,之后也很难添加)。

我喜欢将公开可见的工件添加到 /api 包和内部组件到 /internal 的约定。最终你得到了。

# this package is allowed to be accessed by api-users com.foo.users.api # this is completely internal logic (api implementation) # should only be touched by the api-module itself. com.foo.users.internal

这样你有清晰的分离,也可以运行静态代码分析代码规则。

与上面提到的 servlet-api 一样,您甚至可以进一步将 api 与 impl 拆分为不同的 jar。但这涉及构建生命周期和维护模块的更多努力,因此我只会在完整的运行时工件拆分有意义的情况下这样做(例如在 jsr-spec 与 impl 中)。

【讨论】:

    猜你喜欢
    • 2011-01-14
    • 1970-01-01
    • 2019-03-21
    • 2014-09-01
    • 1970-01-01
    • 2014-01-28
    • 2015-08-07
    • 1970-01-01
    • 2011-09-24
    相关资源
    最近更新 更多