0

让我们想想这个类,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对于 的字段具有 getter 和 setter Clazz1)。

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 应用程序。不可变部分将包含有关我的客户端将与对等方共享的文件集的所有信息,以及一些哈希键以确保接收到的数据包的真实性。而可变部分将包含有关共享状态的信息,即一些状态、上传的字节数、下载的字节数等......不可变部分可以很容易地称为“元信息”,而可变部分可以称为“上下文”,如果你想要更有意义的名字。但我的问题更多是关于这种设计的实用性。感谢您的回答!

EDIT2:我选择的名称只是出于抽象目的,我会在实际实现中给出更好的名称。也就是说,我同意乍一看可能会令人困惑,说“显式”是指将两个部分严格区分为两个不同的对象,而不是明确命名一个部分“不可变”和另一部分“可变” .

4

3 回答 3

1

我建议你划分你的对象不是基于它们是否可以改变的事实,而是它们在你的类的上下文中的含义。

如果你真的想标记不可变的部分,注释甚至可能比改变结构更好,以方便对象数据的可变性。

也不要忘记,你可能有可变数据,你分发不可变的副本。

将可变/不可变变量保存在单独的组中(带有注释)是有道理的,但我真的不建议根据其数据的合理任意属性来更改您的对象是什么(或由什么组成)。

于 2014-10-21T20:32:56.880 回答
1

根据您的详细程度,这无法确定,但有一些额外的要求,这样的拆分可能是可取的。

具体来说,可变部分和不可变部分之间的拆分是享元模式的本质:您可以在所有需要它的实例之间自由重用不可变部分,使其处于相同状态。

您还可以将不可变部分自由地发布给任何相关方,而不会破坏任何内部结构。

此外,如果您需要深度克隆对象,这可能会有所帮助。不可变部分将在克隆之间共享。

于 2014-10-21T20:27:43.090 回答
1

对象由其他对象组成是很常见的,并且其中一些组件是不可变的(例如,用于跨实例共享公共数据)而其他组件是可变的并不罕见。

但是,我不会采用明确调用可变和不可变组件的命名方案。坚持传达其目的的描述性名称。从外部看,可变性通常被认为是整个对象:它的一部分是可变的,在这种情况下,对象被认为是可变的,或者它是完全不可变的。此外,对象的使用者通常更关心对象公开了哪些数据,而不是数据的来源或内部结构,因此在组织和命名成员时请记住这一点。


至于您提出的分离元数据的设计,这是非常有意义的。它与普通的旧 Java 对象没有什么不同:每个对象的元数据(它的类定义)都与实例数据分离并暴露在一个地方:getClass(). 但是请注意,该名称描述的是(元)数据,而不是它的(im)可变性。

于 2014-10-21T20:30:36.817 回答