標籤:down 避免 sel 複雜 its 工廠 組件 本質 lex
Item 15 最小化類的可變性
effective java
如何做到讓類不可變?
- 不提供改變對象狀態的方法。(mutators)
- 確保類不會被繼承,即用final來限定類。
- 讓所有的域(field)為final。
- 讓所有的域private。
- 確保所有對可變組件的互斥訪問(Ensure exclusive access to any mutable components)
例子:
public final class Complex{//final class private final double re; //private final field private final double im; public Complex(double re,double im){ this.re = re; this.im = im; } public double realPart(){return re;} public double imaginaryPart(){return im;} public Complex add(Complex c){ return new Complex(re+c.re,im+c.im); //return new object instead of modify itself } //Other arithmetic method ommit...}
為什麼要使用不可變對象(immutable objects)?
- 不可變對象很簡單。不需要考慮對象在變化中是否會變得行為怪異。只要在構造方法中有限制,不可變對象就一直是有效。
不可變對象本質上是安全執行緒的,不需要同步(synchronization)。不可變對象是鼓勵共用而不用擔心安全。例如以下這種:
public static final Complex ZERO = new Complex(0,0);
- 不可變對象的內部也是鼓勵共用的。
不可變對象作為其他複雜物件的構件(building blocks)是很優秀的。其不變的性質降低了複雜物件的設計難度。
不可變對象的缺點以及最佳化
- 不可變對象的唯一缺點:每次操作都需要建立新對象,在多步操作中造成效能問題。
- 最佳化:
- 在多步操作中使用可變的“伴隨類”(mutable "companion class")。例如String類與String Buffer類。
- 預測哪些多步操作是經常被使用的,提供這些操作的官方方法進行最佳化。
最佳實務
- 提供公有的靜態Factory 方法(static factory method)並讓構造器為私人。
- 可以提前檢測輸入資料的有效性,如果不合法可以直接避免建立對象。
- 可以緩衝一些常用的對象,最佳化效能。
- 可以添加一些實用的功能。
- 製造不可變類的條件可以弱化為任何方法都不能造成對象外部表格現的改變。這樣我們可以創造一些內部的可變組件用於緩衝,進而最佳化效能。
總結
- 設計一個類時首先考慮是否能讓它不可變。
- 如果類不能做成完全不可變的,將其可變性限制到最低。
- 不要在靜態Factory 方法和構造器之外提供任何的初始化方法。
《Effective Java》讀書筆記 - 最小化類的可變性