限制公共可访问成员 - 解决方法

时间:2013-02-27 09:36:28

标签: java oop visibility

我想在逻辑部分'Data','Commands'和'Engines'中破坏我的应用程序模型。应用程序外的每个人都应该获得对数据的只读访问权限并访问命令。使用这些命令,他们可以操纵数据。

其中我已经将我的应用程序包含在包中:

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

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

这个问题有共同点吗?请不要建议我必须等到Java 8,因为我现在想写我的应用程序。将所有类放在一个包中也是没有选择的,因为我会丢失我的应用程序的概述。

修改

我通读了一些关于树木和图表不变性的网站。我见过一个名为zipper的好主意:http://scienceblogs.com/goodmath/2010/01/13/zippers-making-functional-upda/。不幸的是,这似乎不适用于我的情况。

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

为此我给数据类两个公共接口一个readonely和一个可写。每当客户端使用只读实例调用命令时,我只需将其强制转换为可写实例。这种方法解决了我的问题,但有两大缺点。首先,我假设每个只读实例同时是一个可写实例 - 这可能会导致一些丑陋的错误。其次,客户端可以执行相同操作并具有写访问权限。但我可以说自己的错。

有人有更好的主意吗?

2 个答案:

答案 0 :(得分:1)

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

  1. 确保不应访问文档数据(JavaDoc)。
  2. 如果你想变得极端,你可以检查来电的来源并否认(有点矫枉过正)
  3. 作为补充,这里有关于此主题的博文:A simple suggestion to radically improve your package structure

答案 1 :(得分:1)

我为此类问题提供了三种模式。我按照近似的顺序尝试:

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

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

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

我的偏好总是1,因为它会导致更简单的代码,更容易扩展。但是如果我遇到麻烦,那么我倾向于回到2,因为它在方法之间取得了平衡,并且不允许另一个线程正在改变另一个线程后面的实例。它也不需要那么多额外的代码,但它确实需要规则来确保对象被正确锁定并强制执行锁定语义。因此,它在实践中并不是一种非常普遍的模式。