【问题标题】:Restricting public accessable members - workaround限制公共可访问成员 - 解决方法
【发布时间】:2013-02-13 01:21:17
【问题描述】:

我想在逻辑部分“数据”、“命令”和“引擎”中打破我的应用程序模型。应用程序之外的每个人都应该获得对数据的只读访问权和对命令的访问权。通过这些命令,他们可以操作数据。

我已经在包中构建了我的应用程序:

myapp.model.data
myapp.model.commands
myapp.model.engines

引擎和命令都需要对数据进行写访问。因此,我必须以公共接口的形式公开写访问权限。这导致了外部客户端也对我的数据有写访问权限的问题,这是不允许的。这样做的问题是,命令使用事件调用引擎来检查数据的一致性。客户端会在不调用引擎的情况下操作数据,从而破坏数据的一致性。

这个问题有没有常见的做法。请不要建议我必须等到 Java 8,因为我现在想编写我的应用程序。将所有类都放在一个包中也是没有选择的,因为我会失去对应用程序的概述。

编辑

我阅读了一些关于树和图的不变性的网站。我看到了一个叫做 zipper 的好主意:http://scienceblogs.com/goodmath/2010/01/13/zippers-making-functional-upda/。不幸的是,这似乎不适用于我的情况。

回想一下,我有一个复杂的对象图结构,它将随着时间的推移进行操作。目标是限制客户端仅使用我的命令来操作数据。因此,在我的案例中,我没有看到不变性的优势。

为此,我为数据类提供了两个公共接口,一个是只读的,一个是可写的。每当客户端使用只读实例调用命令时,我只需将其强制转换为可写实例。这种方法解决了我的问题,但有两个很大的缺点。首先我假设每个只读实例同时是一个可写实例——这可能会导致一些丑陋的错误。其次,客户端可以做同样的事情并具有写访问权限。但我不能说这是他们自己的错。

有人有更好的主意吗?

【问题讨论】:

    标签: java oop visibility


    【解决方案1】:

    我认为这是文件夹的常见限制(树状结构)。 解决方案:

    1. 确保不应访问文档数据 (JavaDoc)。
    2. 如果你想走极端,你可以检查呼叫来自哪里并拒绝它(有点矫枉过正)

    作为补充,这里有一篇关于这个主题的博文:A simple suggestion to radically improve your package structure

    【讨论】:

    • 这可能是可能的,但我正在寻找的是一个外部世界只能通过命令来操作数据的解决方案。
    • 我想您已经知道可能的解决方案,请阅读:stackoverflow.com/questions/403583/…
    【解决方案2】:

    对于此类问题,我采用了三种模式。按照我尝试它们的大致顺序:

    1) 不可变/无副作用。函数式编程语言强烈推荐的一种技术,java.lang.String 就是一个例子。这里单个实例是不可变的,调用 mutate 会创建一个新实例。可能不适用于您设计命令和引擎接口的方式,但如果您有精力重新设计它们的接口,那么这是一种非常强大的方法,可以减少行数。

    2) 可锁定对象模式。一个对象在首次创建时是可变的,但在共享之前它是“锁定的”。在被锁定后,对变异方法的任何调用都会出错。解锁对象涉及创建对象的新副本。

    3) 为可变实例创建一个只读包装器。这使您可以控制谁可以变异,以及谁可以只读。 java.util.Collections#unmodifiableList(List list) 是这种装饰器样式模式的 Java 运行时示例,它将 setter 方法保留在共享接口上。可以使用完全没有 setter 方法的不同接口。

    我的偏好始终是 1,因为它会导致更简单的代码更容易扩展。但是,如果我对此有疑问,那么我倾向于退回到 2,因为它在方法之间提供了平衡,并且不允许另一个线程在另一个线程后面改变实例的可能性。它也不需要那么多额外的代码,但它确实需要纪律来确保对象被正确锁定并强制执行锁定语义。因此,这在实践中并不是很常见的模式。

    【讨论】:

    • 我喜欢不可变类的想法。这里的问题是我的数据是树形结构并用作 UI 的数据源。我将对此进行调查并尝试找到一个好的解决方案。感谢您的回答。
    • 为不可变数据结构重新设计可能很棘手。 Clojure 使用了一种模式,该模式由哈希树支持,可用于您的案例。它涉及使用不可变哈希映射来实现树。虽然可能在这里为你杀死了,但这是一个有趣的阅读。 blog.higher-order.net/2009/09/08/…
    • 这里的不变性有什么好处。我的数据会随着时间而变化,因此不是一成不变的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-22
    • 2010-10-14
    相关资源
    最近更新 更多