創(chuàng)建實(shí)例 VS 創(chuàng)建型模式
在使用一個(gè)類型的時(shí)候需要涉及到目標(biāo)類型的實(shí)例化問題,在這里就閑侃一下。
有些講述設(shè)計(jì)模式或者設(shè)計(jì)原則等內(nèi)容的書籍上,建議我們:“將客戶端和目標(biāo)類型的實(shí)例化邏輯進(jìn)行解耦”,這樣客戶端就不需要負(fù)責(zé)如何實(shí)例化的職責(zé)了,隱含的意思就是封裝實(shí)例化的過程。這里的關(guān)鍵點(diǎn)是,如果實(shí)例化過程本身非常簡(jiǎn)單自然,例如一個(gè)簡(jiǎn)單的new調(diào)用,是不需要進(jìn)行額外的技巧性封裝的,也就更沒有必要引入一個(gè)第三方的角色來承擔(dān)實(shí)例化過程(例如工廠角色等)。
客戶端兩種獲取實(shí)例的方式:
【不需要第三者引入】
既然要對(duì)實(shí)例化過程進(jìn)行封裝,并進(jìn)而引入一個(gè)中間角色負(fù)責(zé)實(shí)例化的職責(zé),那么如果實(shí)例化過程本身非常簡(jiǎn)單,干嗎還需要引入一個(gè)第三方角色來負(fù)責(zé)實(shí)例化呢???
對(duì)于這種情況下,應(yīng)該是蠻簡(jiǎn)單的,那就是通過構(gòu)造函數(shù)或者靜態(tài)方法接口獲取實(shí)例。
1、普通構(gòu)造函數(shù)。這是語言內(nèi)置支持的,每個(gè)人應(yīng)該都很熟悉了,就不羅唆說明了
2、靜態(tài)接口獲取實(shí)例的方式。遵照《重構(gòu)與模式》一書中的說法,這種靜態(tài)方法暫且成為“creation method”吧。引入這種方式一般有什么必須的理由呢:
1、構(gòu)造函數(shù)的選擇使用有一定的復(fù)雜度,例如構(gòu)造函數(shù)過多、參數(shù)較多、構(gòu)造函數(shù)本身有點(diǎn)難以理解(這往往是該類型代表的概念就有點(diǎn)難以理解^_^)等情況,針對(duì)一些常用的典型的場(chǎng)景提供幾個(gè)靜態(tài)獲取實(shí)例的接口應(yīng)該是對(duì)客戶很有利的。例如你創(chuàng)建一個(gè)Color類型,提供了構(gòu)造函數(shù)雖然并不復(fù)雜,就是RGB三種數(shù)值,那可能順便提供幾種便利的靜態(tài)接口,例如提供系統(tǒng)的紅、黃、藍(lán)等顏色等。關(guān)于這種方式,有一個(gè)極大的負(fù)作用,那就是提供了非標(biāo)準(zhǔn)的創(chuàng)建實(shí)例的方式,這種方式并不能被繼承等。
2、可能限制實(shí)例化過程,并且往往伴隨著管理實(shí)例。例如相應(yīng)的創(chuàng)建型如單件(singleton)、多件等等。這個(gè)大家應(yīng)該也已經(jīng)很熟悉了,就不說了^_^ 只是提醒一點(diǎn),那就是要判斷是否真的需要做這種限制,是否需要Class.newInstance的調(diào)用場(chǎng)景等。
3、通過靜態(tài)接口提供子類型實(shí)例。這通常體現(xiàn)在返回的是本類型,但是真正的實(shí)現(xiàn)類型可能不是該類型的子類型,而又不想將改類型暴露給用戶,希望用戶同一使用該父類型進(jìn)行操作。這種實(shí)現(xiàn)方式對(duì)外是自然的,也符合依賴倒置等原則;對(duì)內(nèi)可能就是不自然的,畢竟是父類型知道了子類型的存在。
【引入第三者負(fù)責(zé)實(shí)例化職責(zé)】
引入的具體角色和意圖的不同而不同,一般常用的如下:
1、實(shí)例化的過程本身并不會(huì)變化,在需要中這種創(chuàng)建過程就是具體的而不是一個(gè)變化的點(diǎn)。這種,一般引入一個(gè)靜態(tài)工廠方法就可以了
2、如果實(shí)例化的過程變化,那就需要封裝,暫且不考慮是何種變化。在面向?qū)ο笤O(shè)計(jì)中,一般遇到變化的點(diǎn)就是將其抽象封裝,進(jìn)而產(chǎn)生一個(gè)抽象概念,然后在應(yīng)用上下文中以引用的方式來使用這個(gè)概念。那好了,如果要封裝的是單一類型實(shí)例化過程的變化,那么就是常用的factory method;同理,如果需要面對(duì)的是創(chuàng)建系列類型實(shí)例化過程的變化,則就使用abstract factory(可以將其視為增強(qiáng)型的factory method^_^);如果這種變化不是正對(duì)類型,而是單純針對(duì)實(shí)例化過程中步驟的,那么用builder來處理一下吧。
第三者的引入,自然會(huì)引入一定的復(fù)雜性,尤其是對(duì)于那些不熟悉設(shè)計(jì)模式的開發(fā)人員而言(例如,factory的引入必然會(huì)隱藏掉具體類型,這對(duì)那些不是很習(xí)慣面向抽象類型編程的開發(fā)者而言,很有可能就會(huì)覺得不自然^_^ )。還有的就是,不恰當(dāng)?shù)囊胄Чh(yuǎn)不如不引入,引入之前一定要給自己一個(gè)充足的理由。 其實(shí),這一點(diǎn)也同時(shí)適用于所有設(shè)計(jì)模式、設(shè)計(jì)技巧等的使用。
【總結(jié)】
總結(jié)起來就幾個(gè)提問,對(duì)實(shí)例過程進(jìn)行處理的時(shí)候需要問自己的問題:
1、是否需要為實(shí)例化過程引入第三者,引入的理由是什么?
2、如果不需要引入,需要對(duì)語言提供的構(gòu)造函數(shù)特性進(jìn)行進(jìn)一步的技巧性處理?
3、如果需要引入第三者,針對(duì)需要引入的理由,這個(gè)第三者的角色又是怎樣的?
本博客中的所有文章、隨筆除了標(biāo)題中含有引用或者轉(zhuǎn)載字樣的,其他均為原創(chuàng)。轉(zhuǎn)載請(qǐng)注明出處,謝謝!
posted on 2008-09-22 16:23 zhuxing 閱讀(475) 評(píng)論(0) 編輯 收藏 所屬分類: 設(shè)計(jì) 、雜談