天天看點

Effctive java 筆記(一)考慮使用靜态工廠方法替代構造方法考慮使用靜态工廠方法替代構造方法

考慮使用靜态工廠方法替代構造方法

1. 建立對象

什麼是靜态工廠方法

在 Java 中,獲得一個類執行個體最簡單的方法就是使用 new 關鍵字,通過構造函數來實作對象的建立。

eg:

Dog dog=new Dog();

Date date=new Date();
           

而靜态工廠方法:

Calendar calendar = Calendar.getInstance();
  Integer number = Integer.valueOf("3");
  
           

像這樣,不通過new關鍵字,通過一個靜态方法得到類的實列的方法就是靜态工廠方法。

2. 靜态工廠方法和執行個體工廠方法和工廠模式

靜态工廠方法:

就是直接可以通過靜态方法來執行個體化一個對象

public class Car{
    public static Car newtInstance(){
        return new Car();
    }
}
Car .newtInstance();
           

建立 Car對象直接調用Car類的靜态方法newtInstance方法來進行實作

執行個體工廠方法:

就是先建立類對象,然後通過對象來調用建立執行個體對象的方法

public class CarFactory {
    public Car newtInstance(){
        return new Car();
    }
}
CarFactory  carFactory  =new CarFactory();
carFactory.newtInstance();
           

工廠模式

靜态工廠方法通常指的是某個類裡的靜态方法,通過調用該靜态方法可以得到屬于該類的一個執行個體;

工廠模式是一種設計模式。具體看設計模式。

如果要說相似的話,靜态工廠方法跟簡單工廠模式倒有那麼點像,不過差別也挺大,簡單工廠模式裡的靜态工廠方法會建立各種不同的對象(不同類的執行個體),而靜态工廠方法一般隻建立屬于該類的一個執行個體(包括子類);

3. 使用靜态工廠方法的優點

1.有名字,可讀性更強

由于語言的特性,Java 的構造函數都是跟類名一樣的。這導緻的一個問題是構造函數的名稱不夠靈活,經常不能準确地描述傳回值,在有多個重載的構造函數時尤甚,如果參數類型、數目又比較相似的話,那更是很容易出錯。

eg:

Date date2 = new Date("0");
Date date3 = new Date(1,2,1);
           

Date 類有很多重載函數,我們發現,可讀性差,不查文檔,不看注釋很難知道其建立的對象的具體含義

2.與構造方法不同,它們不需要每次調用時都建立一個新對象

JDK中的Boolean類的valueOf方法可以很好的印證這個優勢,在Boolean類中,有兩個事先建立好的Boolean對象(True,False)

public final class Boolean implements java.io.Serializable,
                                      Comparable<Boolean>
{
    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code true}.
     */
    public static final Boolean TRUE = new Boolean(true);

    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code false}.
     */
    public static final Boolean FALSE = new Boolean(false);
           

當我們調用Boolean.valueOf(“true”)方法時,傳回的就是這兩個執行個體的引用,這樣可以避免建立不必要的對象,如果使用構造器的話,就達不到這種效果了;

public static Boolean valueOf(String s) {
        return toBoolean(s) ? TRUE : FALSE;
    }
           

3.可以傳回其傳回類型的任何子類型的對象

Class Person {
    public static Person getInstance(){
        return new Person();
        // 這裡可以改為 return new Player() / Cooker()
    }
}
Class Player extends Person{
}
Class Cooker extends Person{
}
           
public static Person getPlayer(){
        return new Player ();//或者return new Cooker();
    }
    
           

4.在建立帶泛型的執行個體時,能使代碼變得簡潔

這條主要是針對帶泛型類的繁瑣聲明而說的,需要重複書寫兩次泛型參數:

class MyMap<K,V> {
    /**
     *
     */
    public MyMap()
    {

    }

    public static <K,V> MyMap<K,V> newInstance(){
        return new MyMap<K, V>();
    }
}
           
MyMap<String, String> map1 = new MyMap<String, String>();
//更加簡潔,不需要重複指明類型參數,可以自行推導出來
 MyMap<String, String> map2 = MyMap.newInstance();
           

不過自從 java7 開始,這種方式已經被優化過了 —— 對于一個已知類型的變量進行指派時,由于泛型參數是可以被推導出,是以可以在建立執行個體時省略掉泛型參數。

Map<String,Date> map = new HashMap<>();
           

4. 使用靜态工廠方法的缺點

1.如果類不含public或protect的構造方法,将不能被繼承

如下類,不能被其它類繼承

class MyMap<K,V> {

    private MyMap()
    {

    }
    public static <K,V> MyMap<K,V> newInstance(){
        return new MyMap<K, V>();

    }
}
           

2.與其它普通靜态方法沒有差別,沒有明确的辨別一個靜态方法用于執行個體化類

是以,一般一個靜态工廠方法需要有詳細的注釋,遵守标準的命名,如使用getInstance、valueOf、newInstance等方法名;

下面是一些靜态工廠方法的常用名稱。以下清單并非完整:

  • from——A 類型轉換方法,它接受單個參數并傳回此類型的相應執行個體,例如:Date d = Date.from(instant);

    of——一個聚合方法,接受多個參數并傳回該類型的執行個體,并把他們合并在一起,例如:Set faceCards = EnumSet.of(JACK, QUEEN, KING);

  • valueOf——from 和 to 更為詳細的替代 方式,例如:BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);

    instance 或 getinstance——傳回一個由其參數 (如果有的話) 描述的執行個體,但不能說它具有相同的值,例如:StackWalker luke = StackWalker.getInstance(options);

  • create 或 newInstance——與 instance 或 getInstance 類似,除了該方法保證每個調用傳回一個新的執行個體,例如:Object newArray = Array.newInstance(classObject, arrayLen);
  • getType——與 getInstance 類似,但是如果在工廠方法中不同的類中使用。Type 是工廠方法傳回的對象類型,例如:FileStore fs = Files.getFileStore(path);
  • newType——與 newInstance 類似,但是如果在工廠方法中不同的類中使用。Type 是工廠方法傳回的對象類型,例如:BufferedReader br = Files.newBufferedReader(path);
  • type—— getType 和 newType 簡潔的替代方式,例如:List litany = Collections.list(legacyLitany);\

總之,靜态工廠方法和公共構造方法都有它們的用途,并且了解它們的相對優點是值得的。通常,靜态工廠更可取,是以避免在沒有考慮靜态工廠的情況下提供公共構造方法。

本文是根據Effctive java和網上部分部落格總結而出。 侵删。

繼續閱讀