[英]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 個類: SimpleClass
、 SimpleObservable
和SimpleObserver
。
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.