制作不可修改的对象

时间:2012-02-18 14:06:23

标签: java oop design-patterns wrapper unmodifiable

我有一个Java应用程序,其中域层与控制器的UI分离。问题是这些控制器可以返回域对象,并且可以将域对象作为参数。

其中一些返回的域对象是可变的,这就是我想要阻止的。我希望UI(或未来的UI)无法在不访问控制器的情况下直接修改域。

我尝试了两个选项:

  • 在第一个中,我确保每个类都实现了一个“不可修改的”接口,其中只包含getter。如果我需要将对象返回到UI,我返回其“Unmodifiable”界面。因此UI只能查看getter。 这样的问题是它们仍然可以很容易地转换为原始对象并获得访问权限。起初我认为这种安全级别已经足够好了,但是有人意外地将某些对象投入使用并以不正确的方式使用它们,并且违反了完整性。

  • 在第二篇文章中,我尝试为每个可以返回的对象提供不可修改的包装器。但问题是这些返回的对象可以用作控制器中方法的参数,因此它们需要在控制器中展开。我试图使uwrap()方法包私有,但是我必须将每个特定的包装类放在与控制器相同的包中,这有点不方便。

编辑:第3个选项:

  • (感谢vic)在第三个选项中,对象由不可修改的包装器包装,但不能被此包装器解包。每个Unmodifiable都链接到Hashmap中的可修改对象。因此,“解包”是通过获取链接到不可修改对象的可修改对象来完成的。

有没有人知道或者有一些想法如何使对象不可修改,以便它们可以被控制器返回,并且可以在它们传回控制器时再次修改它们?

2 个答案:

答案 0 :(得分:2)

如果控制器私下存储对象的可变版本并将其不可变版本返回到“外部世界”,该怎么办?可变版本将具有某种唯一ID,并且控制器将能够通过查找某种unwrapCollection

答案 1 :(得分:2)

转到State设计模式,这是表示对象状态的绝佳选择。

基本上,只要UI想要显示域对象,控制器就会为它提供一个不可变的DTO对象,表示对象本身的快照。这将限制UI层仅包含域对象的不可变快照。当UI想要对域对象进行更改时,它会将不可变状态对象发送到控制器,控制器使用它们在内部修改相应的域对象。