Effective Java Item1 - 靜態工廠方法
September 20, 2017這篇是Effective Java - Consider static factory methods instead of constructors章節的讀書筆記
Item1: 使用static factory method
注意這裡跟Design pattern的Factory method沒有關連 這點說的是 與其開放你的constructor讓你的使用者想new就new 不如用另外一個靜態工廠包裝起來 當你需要這個物件的時後 跟這個static factory method要人 這個method裡面在自己決定怎麼給你人
直接開放constructor給你用是很差的
Foo x = new Foo()
不如這樣
Foo x = Foo.create()
當然constructor是private
而且工廠方法是static 代表說即使不需要依賴這個類別的物件 就可以call這個method
好處
1.工廠方法可以取名字: client看名字就知道應該call哪個工廠方法 而不是去看constructor的參數順序
2.控制物件數: 不一定每次都要創造新的物件給別人 你可以自己決定要給client舊的instance還是new新的 如果創造物件很貴的話 這點就很實用
3.除了回傳class的instance之外 還可以選擇回傳這個class的subclass(3-1) 或者是所有implement同一個interface的class(3-2) 這點讓我們的接口更加靈活
這是最難懂的一個好處 我把他分成兩個方向來細說
3-1:可以選擇回傳這個class的subclass
public class ParentClass{
public static ParentClass getParentObject() { //靜態工廠方法 1
return ParentClass.newInstance();
}
public static ParentClass getChildObject() { //靜態工廠方法 2
return ChildClass.newInstance();
}
}
private class ChildClass extends ParentClass{
public static ChildClass newInstance() {
return new ChildClass();
}
}
ㄜ 為什麼要這樣 為什麼我們要跟parentClass要一個childClass呢 直接跟ChildClass要不是很好嗎 這樣的好處是我們可以隱藏childClass的實作細節
3-2:可以選擇回傳所有implement同一個interface的class
interface-based-framework: 代表著只讓使用者/Client 存取到interface 但事實上我們給他們的卻是那些implement這個interface的class
給個例子
public interface Runnable {
void run();
}
public class RunAnimal {
private static final Dog dog = new Dog();
private static final Cat cat = new Cat();
private RunAnimal(){}
public static Runnable getDog() {//static factory method
return dog;
}
public static Runnable getCat(){//static factory method
return cat;
}
private static class Dog implements Runnable{
@Override public void run() {
System.out("Running fast");
}
}
private static class Cat implements Runnable{
@Override public void run() {
System.out("Running slow");
}
}
}
要用的時候 用interface接他
Runnable myDog = RunAnimal.getDog()
Runnable myCat = RunAnimal.getCat()
myDog.run();
這就是所謂的接口更加靈活
4.代碼更加簡潔
原本長這樣
Map<String, List<String>> m =
new HashMap<String, List<String>>();
重複的東西必須一直寫 現在你可以這樣
Map<String, List<String>> m = HashMap.newInstance();
為什麼可以這樣呢 因為HashMap有generic static factory
public static <K, V> HashMap<K, V> newInstance(){
return new HashMap<K, V>();
}
所以你給他任何的K, V他都可以直接帶進去
壞處
1.如果你的class沒有public或是protected的constructor 就不能有subclass
2.靜態工廠方法跟其他的static方法沒有太好的方法區隔 甚至javaDoc的constructor裡看不到你那些精美的靜態工廠方法
總結
靜態工廠方法跟constructor都有好處 寫程式的時候先考慮靜態工廠方法 如果他帶來的缺點無法接受 再公開你的constructor