让我们考虑一下这个类,ImmutablePart
是一个不可变的纯数据Object
:
public class Clazz1 {
private final ImmutablePart immu ;
private String f1;
private boolean f2;
private int f3;
/** some constructor building up the immu and
setting the fields to init values
...
...
**/
public ImmutablePart getImmu(){return immu;}
public String getF1(){return f1;}
public boolean getF2(){return f2;}
public int getF3(){return f3;}
public void setF1(String f1){this.f1=f1;}
public void setF2(boolean f2){this.f2=f2;}
public void setF3(int f3){this.f3=f3;}
}
在这个阶段使用合成是一种好习惯,更明确一个部分是可变的,另一个是不可变的,还是只是样板?像这样(MutablePart
有Clazz1
字段的getter和setter。
public class Clazz2 {
private final ImmutablePart immu ;
private final MutablePart mutable;
/** some constructor building up the two final objects
...
...
**/
public ImmutablePart getImmu(){return immu;}
public MutablePart getMutable(){return mutable;}
}
EDIT1:可以更具体一点,不可变部分是从包含某种元信息的文件构建的,因此无意更改。可变部分将在运行时发展。让我们想象一下我正在开发一个p2p应用程序。不可变部分将包含有关我的客户端将与对等方共享的文件集的所有信息,以及一些用于确保接收到的数据包的真实性的密钥。而可变部分将包含有关共享状态的信息,即一些状态,上载的字节数,下载的字节数等等......不可变部分可以很容易地被称为" metaInfo",并且可变的part" context",如果你想要更有意义的名字。但我的问题更多的是关于这种设计的效用。谢谢你的回答!
EDIT2:我选择的名称仅用于抽象目的,我会在实际实现中给出更好的名称。也就是说,我同意乍一看可能会让人感到困惑,通过说"明确"我的意思是将两者分成两个不同的对象,而不是明确命名一个部分" Immutable"和另一部分"可变" 。
答案 0 :(得分:1)
根据您的详细程度,这无法确定,但有一些额外的要求可能需要这样的分割。
具体来说,在可变部分和不可变部分之间进行拆分是 Flyweight 模式的本质:您可以在需要它的所有实例之间自由地重用不可变部分。
您也可以自由地将不可变部分发布给任何感兴趣的一方,而不会破坏任何内部。
此外,如果您需要深层克隆对象,这可能会有所帮助。不可变部分将在克隆之间共享。
答案 1 :(得分:1)
对象通常由其他对象组成,并且其中一些组件不可变(例如,用于跨实例共享公共数据)而其他组件是可变的并不罕见。
但是,我不会采用明确调出可变和不可变组件的命名方案;坚持传达其目的的描述性名称。从外部看,可变性通常被认为是整个对象的 :它的任何部分都是可变的,在这种情况下,对象被认为是可变的,或者它是完全不可变的。此外,对象的消费者通常更关心对象所公开的数据,而不是数据来自何处以及内部结构如何,因此在组织和命名成员时请记住这一点。对于您提出的设计,您将元数据分开,这非常有意义。它与普通的旧Java对象没有什么不同:每个对象的元数据(它的类定义)都与实例数据分开,并在一个地方公开:getClass()
。但请注意,名称描述了(meta)数据,而不是其(im)可变性。
答案 2 :(得分:1)
我建议你将对象分开,不是基于它们可以被改变的事实,而是它们在你的课堂环境中意味着什么。
如果你真的想标记不可变部分,注释甚至可能比改变结构更好,以便于对象数据的可变性。
也不要忘记,你可能有可变数据,你可以分发不可变的副本。
将可变/不可变变量保存在不同的组中(带注释)是有意义的,但我真的不建议根据它的数据的合理任意属性来更改对象(或由其组成)。