簡體   English   中英

在 Java 中創建不可變對象的正確方法

[英]Proper way to create immutable objects in Java

我有以下代碼:

package me.immutable;

import java.util.*;

public class Immutable {
    public static void main(String[] args) {
        //this is immutable using builder
        SimpleClass wb = new SimpleClass.Builder()
                .addString("a")
                .addString("b")
                .addString("c")
                .withWillNotChange("notchange")
                .build();

        //this is new immutable with changes only needed properties
        //wb object remains unchanged
        SimpleClass newWb = wb.withDifferentStrings(Arrays.asList("d", "e", "f"));
    }
}

class SimpleClass {
    private final List<String> strings;
    private final SimpleObservable simpleObservable;
    private final String willNotChange;

    private SimpleClass(Builder builder){
        this.strings = builder.strings;
        this.willNotChange = builder.willNotChange;
        this.simpleObservable =
                builder.simpleObservable == null ?
                        new SimpleObservable(strings) :
                        builder.simpleObservable;
    }

    SimpleClass withDifferentStrings(List<String> strings){
        return builder(this)    //create new immutable object using builder
                .withStrings(strings)   //modify only what changes
                .withSimpleObservable(simpleObservable.changeCanChange(strings))
                .build();
    }

    Builder builder(SimpleClass sc){
        return new Builder(sc);
    }

    static class Builder{
        private List<String> strings = new ArrayList<>();
        private SimpleObservable simpleObservable;
        private String willNotChange;

        Builder(){}

        Builder(SimpleClass sc){
            this.strings = sc.strings;
            this.willNotChange = sc.willNotChange;
            this.simpleObservable = sc.simpleObservable;
        }

        Builder addString(String s){
            strings.add(s);
            return this;
        }

        Builder withWillNotChange(String s){
            willNotChange = s;
            return this;
        }

        Builder withStrings(List<String> strings){
            this.strings = strings;
            return this;
        }

        private Builder withSimpleObservable(SimpleObservable simpleObservable){
            this.simpleObservable = simpleObservable;
            return this;
        }

        SimpleClass build(){
            return new SimpleClass(this);
        }
    }

}

class SimpleObservable{
    private SimpleObserver observer;
    private List<String> canChange = new ArrayList<>();

    public SimpleObservable(List<String> canChangeSet){
        canChange.addAll(canChangeSet);
        observer = new SimpleObserver(canChange);
    }

    private SimpleObservable(SimpleObservable so){
        canChange = so.canChange;
        observer = so.observer;
    }

    public SimpleObservable changeCanChange(List<String> canChangeSet){
        //No builder so we use copy constructor to build new immutable object and not change this one
        SimpleObservable o = new SimpleObservable(this);
        o.canChange = canChangeSet; //update only what changes
        o.observer = observer.notifyMe(o.canChange);
        return o;
    }
}

class SimpleObserver{
    private String name;

    public SimpleObserver(List<String> canChange){
        this.name = canChange.get(0);
    }

    private SimpleObserver(SimpleObserver so){
        name = so.name;
    }

    public SimpleObserver notifyMe(List<String> changed){
        SimpleObserver o = new SimpleObserver(this);
        o.name = changed.get(0);
        return o;
    }
}

在這里,我有 3 個類: SimpleClassSimpleObservableSimpleObserver

SimpleClass在內部使用 builder,我可以使用以下代碼僅更改幾個字段來創建它的不可變副本:

return builder(this)    //create new immutable object using builder
                .withStrings(strings)   //modify only what changes
                .withSimpleObservable(simpleObservable.changeCanChange(strings))
                .build();

我怎么能在其他兩個類中使用final字段做類似的事情? 目前我不使用 final 和 copy-constructor 作品。

SimpleObserver o = new SimpleObserver(this);
        o.name = changed.get(0); //if name is final, I could not do this
        return o;

是否有一些選項可以擁有final字段,並保持通過更改少量屬性來創建新的不可變類的能力?

我想沒有比這樣(龍目島)更簡單的方法了,但這不是平面 java 所以......

@Builder(toBuilder = true)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
final class SimpleObservable{
    private final SimpleObserver observer;
    private final List<String> canChange;

    public SimpleObservable(List<String> canChangeSet){
        canChange = new ArrayList<>(canChangeSet);
        observer = SimpleObserver.builder()
                .name(canChangeSet.get(0))
                .build();
    }

    public SimpleObservable changeCanChange(List<String> canChangeSet){
        SimpleObservableBuilder sob = this.toBuilder();
        sob.canChange(new ArrayList<>(canChangeSet));
        sob.observer(observer.notifyMe(sob.canChange));
        return sob.build();
    }
}

@Builder(toBuilder = true)
final class SimpleObserver{
    private final String name;

    public SimpleObserver notifyMe(List<String> changed){
        SimpleObserverBuilder sob = this.toBuilder();
        sob.name(changed.get(0));
        return sob.build();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM