2013-02-27 52 views
1

我想在逻辑部分'Data','Commands'和'Engines'中打破我的应用程序模型。应用程序外的所有人都应该获得对数据的只读访问权限并访问命令。利用这些命令,他们可以操纵数据。限制公共可访问成员 - 解决方法

这个我已经sturctured在包我的应用程序:

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

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

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

编辑

我大约有树木和图表不变性一些网站阅读。我见过一个叫拉链的好主意:http://scienceblogs.com/goodmath/2010/01/13/zippers-making-functional-upda/。不幸的是,这似乎不适用于我的情况。

回想一下,我有一个复杂的对象图结构,它将随着时间的推移而被操纵。目标是限制客户端仅通过我的命令操作数据。所以我没有看到我的情况下不变性的优点。

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

有人更好的主意吗?

回答

1

有是我为这类问题而努力的三种模式。按照大概的顺序,我尝试他们:

1)去不变/副作用免费。一种被函数式编程语言强烈推荐的技术,而java.lang.String就是一个例子。这里一个实例是不可变的,并且调用mutate创建一个新的实例。可能不适用于你如何为你的命令和引擎设计接口,但如果你有能力重新设计他们的接口,那么这是一个非常强大的方法,这往往会减少线数。

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

3)为可变实例创建一个只读包装器。这允许您控制谁可以变异,谁可以只读。 java.util.Collections#unmodifiableList(List list)是这个装饰器样式模式的Java运行时的一个例子,它保持共享接口上的setter方法。人们可以使用不同的接口,根本没有setter方法。

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

+0

我喜欢这个想法不可变类。这里的问题是我的数据是树形结构,并作为用户界面的数据源。我会研究这一点并尝试找到一个好的解决方案。感谢你的回答。 – Yggdrasil 2013-02-27 10:16:33

+0

重新设计不可变数据结构可能会很棘手。 Clojure使用的模式由一个可以用于你的类型的散列树支持。它涉及使用不可变的哈希映射来实现该树。虽然可能在这里杀了你,但它是一个有趣的阅读。 http://blog.higher-order.net/2009/09/08/understanding-clojures-persistenthashmap-deftwice/ – 2013-02-27 10:55:01

+0

这里不变性的优势是什么。我的数据随着时间而改变,因此不是不可变的。 – Yggdrasil 2013-02-27 11:23:04

1

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

  1. 确保您不应访问文档数据(JavaDoc)。
  2. 如果你想要去的极致,你可以检查其中呼叫是来自与否认(有点大材小用)

这里作为补充是关于这一主题的博客文章:A simple suggestion to radically improve your package structure

+0

这可能是可能的,但我所说的是一个解决方案,外部世界只能用命令操作数据。 – Yggdrasil 2013-02-27 10:18:46

+0

我想你已经知道可能的解决方案,阅读此:http://stackoverflow.com/questions/403583/what-is-the-use-of-package-level-protection-in-java – 2013-02-27 10:24:39