Java---靜態(tài)工廠方法

Effective Java刷書筆記---靜態(tài)工廠方法

類實例獲取--“考慮”用靜態(tài)工廠方法代替構(gòu)造器
對于一個類而言箱硕,為了讓調(diào)用者獲取它自身的一個實例冠桃,最常用的方法就是提供一個公有的構(gòu)造器,比如:

    Fragment fragment = new MyFragment();
    Date date = new Date();
    byte[] buf = new byte[2048];
    File dir = new File(path);

而我們也要在日常開發(fā)中“考慮”靜態(tài)工廠方法拢切,靜態(tài)工廠方法也是獲取這個類自身的一個實例律适,他的存在是為了更好的描述和處理這個類葡缰。比如:

    Calendar calendar = Calendar.getInstance();
    Boolean b=Boolean.valueOf(xxx);
  Calendar.java
    public static Calendar getInstance()
    {
      return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
    }
  Boolean.java
   public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }

靜態(tài)工廠方法的優(yōu)勢:

1.靜態(tài)工廠方法有名字。

  • 構(gòu)造函數(shù)的方式 需要名字和類名相同缸榄,當(dāng)有多個重載渤弛,參數(shù)類型、返回值不同等多種情況下(比如Date函數(shù)重載)甚带,對于使用者來說可能閱讀要查閱每個參數(shù)的意義了才能不調(diào)用錯誤的構(gòu)造器她肯。
  • 靜態(tài)工廠方法可以使用不同的方法名字使得其構(gòu)造的對象更加明晰。我們完全可以通過方法名明白構(gòu)造了什么樣的對象鹰贵,幫助客戶端能更好的準(zhǔn)確的調(diào)用正確的實例晴氨。
  • 對于構(gòu)造函數(shù)來說,只有參數(shù)有差異(類型碉输、數(shù)量或者順序)才能夠重載
  • 靜態(tài)工廠方法允許我們有相同的參數(shù)類型籽前,只要名字不同即可。
    即如果構(gòu)造器的參數(shù)本身沒有確切的描述正被返回的對象,那么具有適當(dāng)名稱的靜態(tài)工廠會更容易使用枝哄,代碼更容易閱讀肄梨。

2.不用每次被調(diào)用時都創(chuàng)建新對象。

這一點可能比較好理解挠锥,這樣做避免創(chuàng)建不必要的對象众羡。
有時候外部調(diào)用者只需要拿到一個實例,而不關(guān)心是否是新的實例蓖租;又或者我們想對外提供一個單例時 粱侣。可以用靜態(tài)工廠方式為重復(fù)的調(diào)用返回相同的對象菜秦。
然后順便重溫一下單例: Hi甜害,我們再來聊一聊Java的單例吧

public class Single {
    private static Single instance;
    private Single() {}
    public static Single getInstance() {
        if (instance == null) {
            synchronized (Single.class) {
                if (instance == null) {
                    instance = new Single();
                }
            }
        }
        return instance;
    }
}

3.可以返回原返回類型的子類。

這一點符合設(shè)計模式中的基本的原則之一——『里氏替換』原則球昨,就是說子類應(yīng)該能替換父類尔店。構(gòu)造方法只能返回確切的自身類型,而靜態(tài)工廠方法則能夠更加靈活主慰,可以根據(jù)需要方便地返回任何它的子類型的實例嚣州。
比如我們現(xiàn)在想根據(jù)消息類型返回不同的消息子類(比如文本消息、圖片消息共螺、視頻消息等等)

 public static Message getMessage(TIMMessage message){
        switch (message.getElement(0).getType()){
            case Text:
            case Face:
                return new TextMessage(message);
            case Image:
                return new ImageMessage(message);
            case Sound:
                return new VoiceMessage(message);
            case Video:
                return new VideoMessage(message);
            case GroupTips:
                return new GroupTipMessage(message);
            case File:
                return new FileMessage(message);
            case Custom:
                return new CustomMessage(message);
            case UGC:
                return new UGCMessage(message);
            default:
                return null;
        }
    }

4.在創(chuàng)建帶泛型的實例時该肴,能使代碼變得簡潔

這條主要是針對帶泛型類的繁瑣聲明而說的,構(gòu)造器實例方式需要我們重復(fù)書寫兩次泛型參數(shù):
但如果我們通過靜態(tài)工廠方式藐不,編譯器可以幫我們找到類型參數(shù)(類型推導(dǎo))匀哄,只寫一次泛型參數(shù)。


//常規(guī)實例化方式
Map<String, List<String>> m =
    new HashMap<String, List<String>>();

public static <K, V> HashMap<K, V> newInstance() {
    return new HashMap<K, V>();
}
//使用靜態(tài)工廠方法實例化雏蛮,簡化繁瑣的聲明
Map<String, List<String>> m = HashMap.newInstance();

但是jdk1.7之后做了優(yōu)化涎嚼,不用靜態(tài)方法也可以只寫一次類型參數(shù)了。

5.避免寫很多重復(fù)的代碼挑秉,集中管理法梯,統(tǒng)一修改

這一點在業(yè)務(wù)中很常見,比如android開發(fā)中我們需要在MainActivity 中跳到DetailActivity中犀概,最簡單我們會這樣寫

        String url="";
        Intent intent = new Intent(MainActivity.this,DetailActivity.class);
        intent.putExtra("url", url);
        context.startActivity(intent);

但當(dāng)其他Activity 也要跳到DetailActivity中立哑,我們還是會重復(fù)的寫這種代碼,以至于我們某天需要統(tǒng)一查看都哪些跳轉(zhuǎn)DetailActivity時我們需要全局搜索嗎姻灶?铛绰?或者修改intent傳入?yún)?shù)時,也不方便查找产喉。所以此時我們使用靜態(tài)工廠方式至耻,在DetailActivity中加入這個一個方法:

      public static void jumpToDetail(Context context, String url){
        Intent intent = new Intent(context, DetailActivity.class);
        intent.putExtra("url", url);
        context.startActivity(intent);
    }

此時其他activity再調(diào)用時只需DetailActivity.jumpToDetail(context,url);即可若皱,這樣做省去寫重復(fù)的代碼镊叁,也統(tǒng)一管理參數(shù)尘颓,便于查看調(diào)用者。

靜態(tài)工廠方法的劣勢
  • 類如果不含公有的或受保護的構(gòu)造器晦譬,就不能被實例化疤苹。

如果我們在類中將構(gòu)造函數(shù)設(shè)為private,只提供靜態(tài)工廠方法來構(gòu)建對象敛腌,那么我們將不能通過繼承擴展該類卧土。
但是這也會鼓勵我們使用復(fù)合而不是繼承來擴展類。

  • 一般構(gòu)造器在API文檔會被明確標(biāo)識出來像樊,方便閱讀查看尤莺。而靜態(tài)工廠方法我們主要是靠命名規(guī)范來彌補這一劣勢。

實際上公有構(gòu)造器和靜態(tài)工廠各有用處生棍,我們需要理解各自的長處颤霎,選擇合適的方式提供實例,要“考慮”靜態(tài)工廠涂滴,而不是第一反應(yīng)就是提供公有的構(gòu)造器友酱,根本不考慮靜態(tài)工廠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末柔纵,一起剝皮案震驚了整個濱河市缔杉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌搁料,老刑警劉巖或详,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異郭计,居然都是意外死亡霸琴,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門拣宏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沈贝,“玉大人,你說我怎么就攤上這事勋乾∷蜗拢” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵辑莫,是天一觀的道長学歧。 經(jīng)常有香客問我,道長各吨,這世上最難降的妖魔是什么枝笨? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上横浑,老公的妹妹穿的比我還像新娘剔桨。我一直安慰自己,他們只是感情好徙融,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布洒缀。 她就那樣靜靜地躺著,像睡著了一般欺冀。 火紅的嫁衣襯著肌膚如雪树绩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天隐轩,我揣著相機與錄音饺饭,去河邊找鬼。 笑死职车,一個胖子當(dāng)著我的面吹牛瘫俊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播提鸟,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼军援,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了称勋?” 一聲冷哼從身側(cè)響起胸哥,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赡鲜,沒想到半個月后空厌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡银酬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年嘲更,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揩瞪。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡赋朦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出李破,到底是詐尸還是另有隱情宠哄,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布嗤攻,位于F島的核電站毛嫉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏妇菱。R本人自食惡果不足惜承粤,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一暴区、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辛臊,春花似錦仙粱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至淹遵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間负溪,已是汗流浹背透揣。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留川抡,地道東北人辐真。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像崖堤,于是被迫代替她去往敵國和親侍咱。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容