我寫過一篇《如何創建不可變類》。這篇文章中,我們將看到如何使用建造者模式創建不可變類。當構造器中的參數很多時,並且參數的順序會給人造成困擾的時候,那麼使用建造者模式來創建不可變類就是非常好的方法了。
使用建造者模式來創建不可變類
下面是使用建造者模式來創建不可變類的例子:
import java.util.HashMap;
/**
* @Description
* @Author hzmoudaen
* @Since 2014-5-11
*/
public class ImmutableClass {
//required fields
private int id;
private String name;
//optional fields
private HashMap<String, String> properties;
private String company;
public int getId(){
return id;
}
public String getName(){
return name;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public HashMap getProperties(){
return (HashMap<String, String>)properties.clone(); //返回對象的克隆以避免被客戶端修改
}
public String getCompany(){
return company;
}
private ImmutableClass(ImmutableClassBuilder builder){
this.id = builder.id;
this.name = builder.name;
this.properties = builder.properties;
this.company = builder.company;
}
public static class ImmutableClassBuilder{
//required fields
private int id;
private String name;
//optional fields
private HashMap<String, String> properties;
private String company;
public ImmutableClassBuilder(int i,String nm){
this.id = i;
this.name = nm;
}
@SuppressWarnings("unchecked")
public ImmutableClassBuilder setProperties(HashMap<String, String> map){
this.properties = (HashMap<String, String>) map.clone();
return this;
}
public ImmutableClassBuilder setCompany(String cmp){
this.company = cmp;
return this;
}
public ImmutableClass build(){
return new ImmutableClass(this);
}
}
}
下面的測試代碼爲我們測試到底創建的對象是不是不可變的。
ImmutableBuilderTest.java
import java.util.HashMap;
/**
* @Description
* @Author hzmoudaen
* @Since 2014-5-11
*/
public class ImmutableBuilderTest {
@SuppressWarnings({ "unused", "unchecked" })
public static void main(String[] args) {
// Getting immutable class only with required parameters
ImmutableClass immutableClass = new ImmutableClass.ImmutableClassBuilder(1, "Pankaj").build();
HashMap<String, String> hm = new HashMap<String, String>();
hm.put("Name", "Pankaj");
hm.put("City", "San Jose");
// Getting immutable class with optional parameters
ImmutableClass immutableClass1 = new ImmutableClass.ImmutableClassBuilder(1, "Pankaj").setCompany("Apple").setProperties(hm).build();
// Testing immutability
HashMap<String, String> hm1 = immutableClass1.getProperties();
// lets modify the Object passed as argument or get from the Object
hm1.put("test", "test");
hm.put("test", "test");
// check that immutable class properties are not changed
System.out.println(immutableClass1.getProperties());
}
}
重要的知識點
- 不可變類只有getter方法
- 不可變類只有一個私有的構造器,以Builder對象作爲參數來創建不可變對象
- 如果不可變類的成員變量是可變的(譬如HashMap),我們需要使用深拷貝(deep copy)或者克隆來防止成員變量被更改
- 當可選的成員變量很多的時候,使用建造者模式創建不可變類是不錯的方法