【问题标题】:Interfaces, what if not all implementations use all methods?接口,如果不是所有实现都使用所有方法怎么办?
【发布时间】:2012-04-30 18:04:12
【问题描述】:

我对针对接口进行编程还很陌生,我正在努力将其作为开发测试驱动的主要工具。

目前我们有很多管理器类都实现了CRUD 接口。然而,有些经理还没有进行更新,有些没有删除,有些可能永远不会这样做。


未实现异常?

可以吗,就这样

throw new NotImplementedException()

直到方法被实现,或者如果它从未实现,甚至一直存在?

(很明显,源代码注释告诉程序员“不应该使用这种方法,例如,‘男性’‘女性’这样的类型永远不会被删除)?


拆分?

或者我应该将我的 CRUD 界面拆分为可创建、可读取(可搜索)、可更新和可删除?这不会弄乱我的类定义吗?

PersonManager implements Creatable<Person>, Updateable<Person>, Deletable<Person>, Searchable<Person>

拆分和合并?

或者我应该将所有 4 之类的一些接口组合到 CRUD 中,或许还有其他一些组合,例如读取 + 更新?

也许这也会创建大量接口,其中一个必须单击一个大的继承路径来找出哪个接口实现了当前情况下所有所需的原子接口(我需要读取和创建,所以哪个只实现了两个?这很快就会变得复杂得多)

【问题讨论】:

    标签: java interface implementation


    【解决方案1】:

    IMO,对于中间阶段 - 可以使用 NotImplementedException,直到您完成实施。

    但是,作为一种永久性解决方案 - 我认为这是一种不好的做法 [在大多数情况下]。

    相反,我会创建一个包含所有实现类共有的行为的接口,并使用子接口将它们聚集起来以实现更具体的行为。

    这个想法类似于 java 标准 SortedSet,它扩展了一个 Set - 我们不想将 Set 视为 SortedSets并给这种类型的变量赋值HashSet,而不是为此我们使用子接口SortedSet

    【讨论】:

    • 重要的反例:Collection(及其子接口)上的所有修改方法都标记为可选,并明确记录允许抛出UnsupportedOperationException。将其移至 MutableCollection(或额外的 StructurallyMutableCollection)会使集合 API 变得一团糟。
    • @JoachimSauer 感谢您的输入,我不认为这里有黑白 - 有很多灰色区域,但我相信您的 [好] 示例是例外,而不是普通,你同意吗?我添加了一个指示,我的意思是在大多数情况下 - 并不总是在答案中。
    • @JoachimSauer 这是 java 标准库的故意违约,而不是“最佳实践”。不从接口中删除不受支持的方法使整个概念变得相当模棱两可 IMO。现在你可以拥有implement 一个接口但实际上根本不实现它的类。
    • @soulcheck:我知道,在所有情况下这绝对不是正确的做法,但我仍然认为他们在这种情况下做了正确的事情。这就是我想要展示的全部内容:没有明确的界限可以总是导致正确的决定。
    • @JoachimSauer 是的,在语义方面我是个纯粹主义者,尤其是对于这样一个基本的语言概念,所以从不喜欢 sun 支持可选操作的决定。
    【解决方案2】:

    一般你想抛出UnsupportedOperationException,这是一个运行时异常,明确提到不支持请求的操作。

    拥有大量界面会导致文件过多,而且如果有人试图查看它们,他们会感到困惑。在这种情况下,Java 文档也无济于事。

    如果一个接口的操作太多,并且并非所有操作在逻辑上绑定在一起,则拆分接口是有意义的。

    对于数据库操作,这种情况很少发生,因为您将进行一些基本操作,这在大多数情况下都是正确的。

    【讨论】:

    • 同样,大多数开发人员不应该直接针对 DAO 进行编码。相反,他们应该使用抽象 DAO 访问的更高级别的业务对象。那些使用 DAO 的人会熟悉哪些 DAO 支持哪些操作。当然,您会大量评论它们,对吗? :)
    • 那些经理并不完全是 DAO。他们访问 DAO 层,但他们也知道如何在对象被持久化之前设置它,即检查条件、引用、创建依赖项……还不确定,我是否应该像我们一样将这些任务移到 DAO“提供者”中调用它们,它们目前仅支持基本操作,例如针对休眠的保存刷新、删除等。
    【解决方案3】:

    NotImplementedException 并不意味着该类不支持此操作。这意味着它没有实现,但它会在未来实现。

    从逻辑的角度来看,所有接口方法都必须实现,并且必须运行良好。但是如果你离开它,只为自己编写一个应用程序,那么你就会记住这个限制。另一方面,我会很生气一些开发人员实现了接口并没有实现它。所以我认为你不能为了未来的发展而留下不实现的接口方法。

    我的建议是修改接口,然后在实现的方法中使用异常。

    【讨论】:

      【解决方案4】:

      在支持协变和逆变的框架中,拆分接口然后定义一些复合接口可能非常有用。对于不提供此类支持的框架(甚至有时在提供此类支持的框架上),有时让接口包含各个实现可能支持或不支持的方法会更有帮助(当尝试不受支持的操作时,实现应该抛出异常);如果要这样做,则应包含方法或属性,外部代码可以通过这些方法或属性询问支持哪些操作,而无需使用任何会引发异常的代码。

      不过,即使在使用对操作的支持是可选的接口时,定义额外的接口以保证某些操作可用,有时也可能会有所帮助。拥有在不添加新成员的情况下继承其他接口的接口可能是实现此目的的好方法。如果做得好,代表实现所需的唯一额外工作是确保它们将自己声明为适用的最具体的类型。客户的情况稍微复杂一点:如果客户的需求可以在类型系统中充分表达,客户可以通过要求特定类型来避免运行时类型检查的需要。另一方面,在客户端之间传递实例的例程可能会因为某些客户端需要比传递实例的代码本身需要的更具体的类型而变得复杂。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-05
        • 2015-03-28
        • 1970-01-01
        • 2016-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-30
        相关资源
        最近更新 更多