1. 程式人生 > >Effective Java -- 用靜態工廠方法來代替構造器

Effective Java -- 用靜態工廠方法來代替構造器

本文是 《Effective Java》的讀書筆記,由於是Java進階書,難免會有理解的偏差,發現有錯誤,非常歡迎能提出來,本人不勝感激!

為什麼要考慮使用靜態工廠方法代替構造器呢?本書中說明了以下的優點:

(1)靜態工廠方法能提供一個可讀性很高的名稱來幫助你理解你要返回的物件是什麼

利用書上的例子,在型別BigInteger中提供了一種建構函式:

    public BigInteger(int bitLength, int certainty, Random rnd) {
        //……
    }

這個建構函式很大概率返回的是一個素數(概率為(1(2100)

但是這個名字基本不能看出來他返回的可能為素數,於是利用靜態工廠方法來表示,那就容易理解多了:

    public static BigInteger probablePrime(int bitLength, Random rnd) {
        //……
    }

在前臺我們寫的程式碼的可讀性是不是強多了:

BigInteger bi1=BigInteger.probablePrime(4,new Random());

(2)可以避免建立不必要的重複物件

如果我們需要經常的建立相同的物件,在建立物件的代價很高的時候,這個技術可以很好的去提升效能。

如下,我們看一下Boolean.valueOf(boolean)方法

    public static
Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }

這樣就使得我們程式每次使用的都是我們我們預先建立好的例項,達到重複利用的效果。

在實現Singleton的時候,我們就使用了靜態工廠方法,如下:

class MySingleton{

    private static MySingleton mySingleton=null;

    public static MySingleton newInstance(){
        if(mySingleton==null){
            MySingleton.mySingleton=new
MySingleton(); } return mySingleton; } }

[ 注 ]:以上只是最基本的單例,如需瞭解更多,歡迎訪問:實現執行緒安全的Singleton

(3)可以返回原返回型別的任意子型別

在基於介面程式設計的框架中,如果我們不確定該介面要返回哪一種例項化的類(如果要根據相應的引數資訊來判斷),就可以使用靜態工廠方法了。
舉個簡單的例子,如下程式碼

        Map<Object,Object> hashMapObj=new HashMap<Object, Object>();
        Map<Object,Object> treeMapObj=new TreeMap<Object, Object>();

一個Map介面可以例項化為HashMapTreeMap等幾種例項化類,如果我們需要根據傳入的引數的資訊判斷該返回HashMap還是TreeMap,就可以寫出如下程式碼:

Map<Object,Object> hashMapObj=Map.getInstance(Object obj);

然後再在 Map 類中寫如下的靜態工廠方法

public static<K,V> Map<K,V> getInstance(Object obj){
    if(/*引數obj滿足某某條件*/) {
        return new HashMap<K, V>();
    }
    if(/*引數obj滿足某某條件*/) {
        return new TreeMap<K, V>();
    }
    /*……*/
    /*等等等等*/
}

上面的程式當然只是我的假想,當然你可以把這個思想用到自己構造的介面中去。

那麼在Java有沒有這樣的用法呢?當然是有的,我們來看一下EnumSet中的noneOf()方法,如下

    public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
        Enum<?>[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");

        if (universe.length <= 64)  //如果長度小於64,則返回RegularEnumSet型別
            return new RegularEnumSet<>(elementType, universe);
        else                        //反之,返回JumboEnumSet型別
            return new JumboEnumSet<>(elementType, universe);
    }

在這個靜態工廠方法中,就通過判斷傳入的底層列舉型別的大小(元素的個數),來選擇返回的例項(如上程式碼註釋)。

(4)在建立引數化例項的時候,可以使得程式碼更加的靈活

例如在建立一個Map<K,V>例項的時候,經常會使用如下程式碼:

Map<Object, Object> hashMapObj = new HashMap<Object, Object>();

如果Object型別又是一個複雜型別,這樣迴圈,程式碼就會變得越來越冗長,如果HashMap提供瞭如下靜態的工廠方法,則就簡化程式碼了。(事實上沒有)

public static<K,V> HashMap<K,V> getInstance(){
    return new HashMap<K,V>();
}

然後在建立一個Map<K,V>例項的時候就可以使用下面簡化的程式碼了:

Map<Object, Object> hashMapObj = HashMap.getInstance();

當然,在更高的JDK版本中,可以直接使用下面的寫法

Map<Object, Object> hashMapObj = new HashMap();

套用一句以前常說的一句話:Every coin has two sides
那我們來看一下 靜態工廠方法有哪些缺點吧

(1)一個類如果不含共有的或者受保護的構造器,就不能被子類化(即不能被其他的類繼承)

(2)對於提供了靜態工廠方法來例項化類的類,我們在查明相應方法的時候,會有一點點的困難。
在遵循一定的命名規範的時候,可以彌補這一缺點,如下的一些管用名稱:

名稱 例項
valueOf Boolean.valueOf()
of EnumSet.of()
getInstance Calendar.getInstance()
newInstance DocumentBuilderFactory.newInstance()
getType Character.getType()
newType 尚未邂逅……

靜態工廠方法和構造器各有用處,靜態工廠通常更加合適,在實際程式設計中要多多考慮。
教學視訊連結:Effective Java 之 用靜態工廠方法來代替構造器

相關推薦

Effective Java -- 靜態工廠方法代替構造

本文是 《Effective Java》的讀書筆記,由於是Java進階書,難免會有理解的偏差,發現有錯誤,非常歡迎能提出來,本人不勝感激! 為什麼要考慮使用靜態工廠方法代替構造器呢?本書中說明了以下的優點: (1)靜態工廠方法能提供一個可讀性很高的名稱來

讀書筆記-《Effective Java》第1條:考慮靜態工廠方法代替構造

優勢 它們有名稱    構造器沒有名稱, 當一個類有多個構造器的時候就不容易分清楚哪個是自己想要的。 不必在每次呼叫它們的時候都建立一個新物件 如果新建立的物件的成員屬性是可以重用的, 那麼可以先把第一次建立的物件儲存起來,以後想用的時候就不用

Effective Java-考慮靜態工廠方法代替構造

public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; } //使用構造器 Boolean b1 = new Boolean(true); //使用靜態工廠方

[Effective Java]考慮靜態工廠方法代替構造

本文主要介紹如何使用靜態工廠方法已經在那種場合來使用這種方式代替構造方法。        眾所周知,對於類而言,我們為了獲得一個類的例項物件,通常情況下會提供一個公有的(public) 的構造器。當然

effective java】考慮靜態工廠方法替代構造

這裡所說的靜態工廠方法就是返回型別例項的靜態方法。 那麼為什麼不使用構造器呢?用構造器方式構造例項不是我們一直約定好的嗎? 嘿嘿 主要原因還是我們的構造器方法規定的太多限制了我們程式的靈活性: 構造器規定一:構造器只能本類例項,不能返回子類例項對吧。 構造器規定二:構造器一

EffectiveJava讀書筆記——考慮靜態工廠方法代替構造(一)

無法 父類 應該 樹結構 對象 如何 log 筆記 工廠類 參考網址:http://blog.csdn.net/mingyunduoshou/article/details/6149758 http:[email protect

靜態工廠方法代替構造、遇到多個構造參數時要考慮構建

泛型 不用 推斷 frame public 多參數 eof ram api 一、用靜態工廠方法代替構造器 類通過共有的構造方法可以提供很大的優點:1、構造方法可一有不同的名字,我們可以通過名字區分構造什麽樣子的對象,而構造器名字相同,當參數列表的數目相同 順序不同時 很大的

Java中用靜態工廠方法代替構造的優缺點

Effective Java學習筆記,靜態工廠方法的善用。 一般情況下,對於類而言,我們獲取一個類的例項時,最常用的方法是提供一個公有的構造器。 但是還有一種方法,類可以提供一個公有的靜態工廠方法,它只是個返回類的例項的靜態方法而已。但是靜態工廠方法卻又許多妙用之處。

Tips1:考慮靜態工廠方法代替構造

用靜態工廠方法來代替構造器為外界提供物件 描述: 靜態工廠方法代替構造器來給外界提供物件,建立物件依然是由構造器來完成的 建立物件和提供物件: 建立物件的方式: 構造器 提供物件來哦方式: 構造器 類中公有的靜態方法 一般在使用靜態工廠方法時,會根據方法的需要提供private的構造器 靜

Effective Java靜態工廠代替構造(一)

優勢1:它們有名稱,所以在多個構造器時,能夠根據靜態工廠的方法的名稱找到哪個構造器。 優勢2:能夠實現單例模式,不必在每次呼叫重新建立新物件。 優勢3:當建立引數化引數例項時,使用靜態工廠方法更加簡單。 優勢4:它們可以返回原返回型別的任何子物件。 書中

EffectiveJava讀書筆記- 第1條:考慮靜態工廠方法代替構造

考慮靜態工廠方法代替構造器 靜態工廠方法相對於構造器的好處: 1. 靜態工廠方法有名字,相比構造器建立的物件更語義化 最好的例子就是併發庫中的Executors工具類了。 Executors中有多個建立執行緒池的方法: public static

1. 【建立與銷燬物件】考慮靜態工廠方法代替構造

本文內容為《Effective Java》的讀書筆記。 對於某一個類,要獲取其物件,通常是使用共有的構造方法new一個。其實還有另一種方法也是經常用到的,那就是靜態工廠方法。 (注:此處的靜態工廠方法不同於工廠模式) 舉個例子: public static Int

01、考慮靜態工廠方法代替構造

優點 1. 有名稱,當一個類需要多個帶有相同引數的構造器時,就可以用靜態工廠方法代替構造器,並且慎重地選擇名稱以便突出它們之間的區別 例如下邊的有關汽車的類,可以使用三個靜態工廠方法返回不同的汽車 public class Car { private String nam

1、靜態工廠方法代替構造

一、客戶端獲取類的一個例項,有兩種解決方案 最傳統的方法就是提供一個公有的構造器。 類提供一個公有的靜態工廠方法,返回一個類的例項的靜態方法。 二、靜態工廠方法的優點 1、有方法名,可讀性強 不同的靜態工廠方法,有自己的專屬名稱。如果構造器的引數本身沒有確切地描述正被返回的物件,那麼具有名稱的靜態工廠方

1.考慮靜態工廠方法替代構造

public final class Boolean implements java.io.Serializable,Comparable<Boolean>{ public static final Boolean TRUE = new Boolean(true);

Effective Java靜態工廠構造一)

前言:因為是直接看完Think in Java後就入手Effective Java的,所以在閱讀的過程中難免有些不懂,便以一種閱與查的方式很費勁的去儘量的多深入瞭解Java,希望在看完後能夠有很大的提升,並將這一過程所獲以筆記形式記下來 第一條的標題是考慮用靜態工廠方法代

Java 8 新特性———方法引用和構造引用

1.方法引用 當要傳遞給Lambda體的操作,已經有實現的方法了,可以使用方法引用!(實現抽象方法的引數列表,必須與方法引用方法的引數列表保持一致!)方法引用:使用操作符“::” 將方法名和物件或類的名字分隔開來。 如下三種主要使用情況: 物件::例項方法 類::靜態方

工廠方法(虛構造

核心 form class 具體類 同時 {} 多個 道具 cat 工廠方式的核心是定義一個抽象工廠接口類,將對象的創建工作推遲到工廠接口類的子類中。 即不同對象創建依賴繼承自工廠基類的關聯工廠子類。 相較於簡單工廠,工廠方法模式符合開閉原則,同時實現了解耦,但出現了類膨脹

Effective Java讀書筆記】創建和銷毀對象(一):考慮使用靜態工廠方法代替構造

返回對象 boolean 簡化 將不 其他 種類型 bigint color pre 類可以提供一個靜態方法,返回類的一個靜態實例,如Boolean包裝類的一個獲取實例的靜態方法 1 public static Boolean valueOf(boolean b) { 2

effective Java 1 使用靜態工廠方法代替構造

jdk Boolean類的原始碼:public final class Boolean implements java.io.Serializable, Comparable<Boolean> { public static final