雖然使用constructor直覺又快速,但是使用static factory method去create instance,還是比constructor好,當然也會有一些缺點,下面將分析這些優缺點:
因為constructor沒有名稱,會讓使用者難以知道要如何使用,透過static method去create或取得物件,會更清楚知道使用這個method做這件事的目的,可以依照不同需求,設計不同的static method,而不是像constructor,只能設計不同參數數量的多個constructor,使用者要使用時,還要弄懂每個constructor符不符合自己的需求。
使用static factory method可以避免產生重複的object,如果使用constructor取得物件的話,每次都會create一個新的物件,但是如果是使用使用static method取得物件,如果相同的物件已經create過了,並且被cache住,就可以直接取用現有的物件,不需要再重複產生,這樣可以讓效能更佳,在記憶體比較珍貴的地方,這個優點會特別重要。
如果需要根據不同的參數,回傳不同類型的subclass,使用static method也可以根據不同情境取得所需的subclass,舉例來說,要知道動物中大象腳的數量,可以在Animals這個class透過method取得Elephant這個實作Animal的instance,如果是直接用Animals的constructor,無法直接Animals透過取得Elephant的instance,還是需要透過Elephant的類別實體化,會少了一點彈性。
interface Animal {
public int getFootNumber();
}
class Elephant implements Animal {
public int getFootNumber() {
return 4;
}
}
class Monkey implements Animal {
public int getFootNumber() {
return 2;
}
}
public class Animals {
private Animals() {};
public static Animal newInstance(String name) {
if (name.equals("elephant")) {
return new Elephant();
} else if (name.equals("monkey")) {
return new Monkey();
}
return null;
}
public static void main(String[] args) {
Animal elephant = Animals.newInstance("elephant");
System.out.println("foot number: " + elephant.getFootNumber());
}
}
可以不用一開始就決定type parameter的型別。以hashmap為例,在一開始宣告的時候,如果是透過constructor,Java 7之前必須在new instance的時候指定type parameter的型別,因此會需要寫重複的程式碼,變得很冗長。
Map<String, List<String>> m = new HashMap<String, List<String>>();
但透過static factory method的方式,可以先把類別的type parameter宣告成泛型,然後在宣告的時候,在透過宣告的參數型別指定type parameter的型別,程式碼會變得比較簡潔。
public class HashMap{
public static <K, V> HashMap<K, V> newInstance() {
return new HashMap<K, V>();
}
}
Map<String, List<String>> m = HashMap.newInstance();
但在Java 7之後引入了Diamond Operator之後,讓編譯器可以自行推斷物件實體化之後的type parameter的型別,更近一步的簡化寫法,這個優點就沒有那麼明顯。
Map<String, List<String>> m = new HashMap<>();
如果將constructor設為private,那麼class會無法被繼承,在編譯的時候會出現錯誤。
class Animals {
private Animals() {};
public static Animal newInstance(String name) {
if (name.equals("elephant")) {
return new Elephant();
} else if (name.equals("monkey")) {
return new Monkey();
}
return null;
}
}
class Life extends Animals {
}
因為不像constructor有特殊意義,大家知道可以拿來new instance,自行寫static factory method取代constructor的功能,容易跟其他static method的功能混淆。