第1條:考慮用靜態工廠方法代替構造器

通常我們創建對象的方法有兩種:

  1. 使用類公有的構造器

  2. 使用類的靜態方法返回一個實例對象

靜態方法的優點:

1.靜態工廠方法與構造器不同的第一大優勢在於,它們有名稱

靜態工廠方法的名字由自己命名,而構造方法必須與類名相同。

//使用構造器方法獲取到一個素數
BigInteger prime = new BigInteger(int, int ,Random);
//使用靜態工廠方法
BigInteger prime = BigInteger.probablePrime(int, Random);

我們可以通過靜態工廠方法名明確知道我們要獲取到的是一個素數。

2.不必在每次調用它們的時候都創建一個新對象

構造方法每次調用都會創建一個對象,而靜態工廠方法則不會每次調用時都創建要給對象。

靜態方法通常會使用預先構建好的實例或者將構建好的實例緩存起來,進行重複利用,從而避免創建不必要的重複對象,比如我們常見的單例模式。

public class Singleton { /* * 利用一個靜態變量來記錄Singleton類的唯一實例 */

    private static Singleton uniqueInstance; /* * 聲明爲private,使得只有Singleton類內纔可以調用構造器 */

    private Singleton() {
    } /* * 通過該方法實例化對象,並返回這個實例 */
    public static Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }

        return uniqueInstance;
    }
}

上面爲懶惰式單例模式,工程中不能用。

3.靜態工廠方法可以返回原返回類型的任何子類型對象

這樣使我們在選擇返回對象的類時就有了更大的靈活性。

class Father {
    private Father() {
    }

    public static Father newInstance(String type) {
        if (type.equals("ChildA")) { // 根據類型判斷返回那個子類對象
            return new ChildA();
        } else {
            return new ChildB();
        }
    }

    public void getName() { 
        System.out.println("My name is father");
    }

    private static class ChildA extends Father {
        public void getName() { 
            System.out.println("My name is child A");
        }
    }

    private static class ChildB extends Father {
        public void getName() {
            System.out.println("My name is child B");
        }
    }
}

public class Test {
    public static void main(String[] args) {
        Father c1 = Father.newInstance("ChildA");
        c1.getName();
        Father c2 = Father.newInstance("ChildB");
        c2.getName();
    }
}

4.靜態工廠方法在創建參數化類型實例的時候,可以使代碼變得更加簡潔

//構造方法 
Map<String,List<String>> map = new HashMap<String,List<String>>(); 
//靜態方法 public static <K,V> HashMap<K,V> newInstance(){
    return new HashMap<K,V>(); 
}
Map<String,List<String>> map = HashMap.newInstance();

但實際上,現在Java最新的版本已經構造函數已經不需要補充參數了。

HashMap<String,List<String>> map = new HashMap<>();

靜態方法的缺點:

1.類如果不含有公有的類或者受保護的構造器,就不能被子類化

2.它們與其他的靜態方法實際上沒什麼區別,因此我們約定了一些靜態工廠方法的常用名稱:

valueOf——不太嚴格的講,該方法返回的實例與它的參數具有相同的值。這樣的靜態工廠方法實際上是類型轉換方法。

of——valueOf的一種更爲簡潔的替代,在EnumSet中使用並流行起來。

getInstance——返回的實例是通過方法的參數描述的,但是不能夠說與參數具有同樣地值。對於Singleton來說,該方法沒有參數,並返回唯一的實例。

newInstance——像getInstance一樣,但newInstance能夠確保返回的每個實例都與所有其他實例不同。

getType——像getInstance一樣,但是在工廠方法處於不同的類中的時候使用。Type表示工廠方法所返回的對象類型。

newType——像newInstance一樣,但是在工廠方法處於不同的類中的時候使用。Type表示工廠方法所返回的對象類型。

簡而言之,靜態工廠方法和共有構造器都各有用處,我們需要理解他們各自的長處。靜態工廠通常合適,因此切忌第一反應就是提供共有的構造器,而不先考慮靜態工廠。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章