設計模式學習05—原型模式

來源:互聯網
上載者:User

標籤:java   設計模式   prototype   原型模式   

一、動機與定義
     之前學習原型模式一直以為原型模式目的是為了方便的建立相同或相似對象,用複製對象的方式替換new的方式,還研究了深複製和淺複製。最近仔細看了GOF的設計模式,發現原型模式的本意並不僅僅是複製對象這麼簡單。     複製對象確實是一方面,當我們需要大量相似,甚至相同對象的時候,除了一個個的new之外,還可以根據一個原型,直接複製出更多的對象。但是如果把原型模式認為只是複製對象這麼簡單就錯了。     建立型模式主要講如何建立對象,通常包含何時建立,誰來建立,怎麼建立等。GOF書裡面寫的意圖是,用原型執行個體指定建立對象的種類,並且通過拷貝這些原型對象建立新的對象。也就是說原型模式應該理解成先指定好要建立的對象種類,也就是指定物件類型,再通過拷貝方式建立對象。     此時再看原型模式定義就更清晰了:用原型執行個體指定建立對象的種類,並且通過複製這些原型建立新的對象。     原型模式的目的是建立對象,通過複製的方式來建立對象,複製只是一種方式、一種方法、或者說一種手段,而不是目的,重點在建立對象上,而不是複製上,如果把重點放到複製對象上,那就變成了研究深複製,淺複製這些東西,他們僅僅是建立對象的一種方法而已,沒有這些複製,我們自己實現複製也完全可以。
二、結構與類圖
     原型模式類圖如下:     
     Prototype:聲明一個複製自身的介面,可以是介面或類,其實複製自身不一定非要所有狀態必須一樣,後面會有提到。          ConcretePrototype:被複製的類,實現了複製自身的操作。     Client:讓一個原型複製自身,從而建立一個新對象。     但是在Java中提供了一個本地clone方法來高效複製對象,為了讓所有類能夠使用通用的clone方法而且不受單一繼承的影響,就把clone放到到了Object中,如果想使用,只需要實現Cloneable這個標記介面就行。這個只能說Java提供了非常便利的方法讓我們直接使用原型模式(相似的還有很多,比如觀察者java.util.Observer等)。而Java預設提供的這個clone只會複製基本類型和String,也就是通常所說的淺複製,要是所有對象都複製,就要自己實現深複製了。
三、適用情境及效果(優缺點)
     先說我之前的理解,之前一直覺得原型模式有兩個重點,一是通過複製代替new了,所以適用情境通常是new一個對象比較困難、代價大,複製方便簡單時使用;二是複製對象能儲存對象狀態,所以需要保留對象狀態時使用。通常有下面幾個適用情境:     1、建立對象成本較大時,直接複製一個對象就非常簡單。這個成本指很多方面,如時間花費較長、資源佔用較多、初始化過程繁瑣等等。     2、系統需要對象狀態時,比如某個對象有10個狀態(或者說屬性),我需要一個和這個對象9個狀態相同,只有1個狀態不同時,原型模式非常方便(有些情況重新建立可能甚至無法擷取從前的狀態了),舉個例子,我要建立一個資源訪問配置,配置好了資源位置、讀取方式、緩衝大小、存取權限,訪問密碼等等,當訪問另一個資源時,只有位置不同,其他的完全相同,此時就可以直接複製一個對象,然後修改一下資源位置狀態即可。     3、一個對象對應多個修改者的情況,當一個對象供多個修改者使用時,比如多線程修改一個對象時,可以考慮使用原型模式建立多個相同對象供調用者使用,從而避免資源競爭,加鎖等(這個要看你的需求,如果目的是共用資源訪問,就不能這樣了)。
     其實這些也沒問題,但是和GOF說的還有一定差距,GOF說了4種適用情境:     1、當一個系統應該獨立於它的產品建立、構成和表示時,要使用Prototype模式。這句話範圍很廣泛,其實依賴倒置原則下的一個解決辦法,調用者不能依賴具體,只能依賴抽象,但是調用者不知道具體產品是哪個時怎麼辦,原廠模式是直接向工廠要一個對象,建造者是嚮導演類要一個對象,單例是向單例類要一個對象,而原型模式是從一個已有的對象上要對象,要一個和你一模一樣的對象。     2、當要執行個體化的類是在運行時刻指定時,例如,通過動態裝載。這個指需要動態建立物件類型,如開發遊戲中的地面類型,有草地、雪地、水泥地等等,程式先建立好各種土地的原型,運行時根據參數來判斷具體要建立哪種類型土地,找到類型對應的原型後,複製即可。     3、為了避免建立一個與產品類層次平行的工廠類層次。這個就是有時候可以代替抽象原廠模式,不是不需要工廠和Factory 方法了,而是把Factory 方法放到自己的clone方法中,把自身當成工廠了,這樣就能減少工廠類。雖然clone方法名字是複製自身,其實不一定就非得複製一個狀態完全一模一樣的對象,有時候只要物件類型一樣即可,也不一定就要複製一個新的對象,有時候把自己return出去也是可以的(和單例結合使用)。     4、當一個類的執行個體只能有幾個不同狀態組合中的一種時。建立相應數目的原型並複製它們可能比每次用合適的狀態手工執行個體化該類更方便一些。這個是解決“只有固定的幾類,每類對象可能有多個時”建立對象的情況,比如中國象棋中的棋子,只有固定7類(車馬象士將炮兵),不會新增其他類的,每類有多個對象(兵有5個,炮有2個等),我們可以先把每種棋子都初始化好(7類棋子),用到的時候覆制一個自己就行了。
//棋子public class Piece {    // 類型    private int type;    // 名字    private String name;    // 狀態    private String state;    // 顏色    private String color;    // 其他屬性......}
     當然,如果種類固定,數量也固定,那可以考慮使用泛型了。     在說說使用後的效果,也就是優點:     1、和工廠、建造者模式一樣,封裝底層實現,依賴抽象產品,隱藏了具體的產品,減少代碼複雜度(類少了)等等,這裡就不詳細說了。     2、運行時刻增加和刪除產品,這個指使用者使用不同產品時,無需建立新的產品類,可以使用一個屬性狀態等來控制物件類型,如上面例子中的棋子,就沒必要為每種棋子建立一個類,只需要一個type就能控制是哪類棋子,調用者使用時,可以自行動態建立和減少產品類。也減少了類數量,簡化了代碼。不過這個要看實際情況,對象種類都特別相似的情況下才可以。     3、改變值以指定新的對象,和上面類似,只需要修改產品屬性值就能建立一個新的產品,非常方便。     4、改變結構以指定新的對象,這個就是直接一個深複製建立一個完全新的產品,直接使用,非常方便。比如做汽車輪胎,需要4個,建立1個輪胎成本較大,但是建立1個後,複製4個就很簡單了。     5、減少子類的構造,前面也說了,相比工廠等方法,減少了工廠類,clone方法直接放到了產品裡面,新增一個子類,不用增加工廠等,簡化了代碼。     6、用類動態配置應用,我們可以將一些配置都放到一個對象中,使用時對外提供這個設定物件的副本即可,這樣動態修改設定物件後,不影響舊的對象使用,而新的使用到配置的地方可以用新的配置。     缺點:     1、原型模式缺點也是顯而易見的,所有子類都必須實現clone方法,新設計的程式還好,原始程式改造時就麻煩了,逐個給所有類加一個clone方法太難了。     2、無法複製問題,複製對象的方式看起來很好,但是有個問題,有些對象不能複製怎麼辦,有些對象複製起來太複雜怎麼辦,比如java中的屬性使用了final關鍵字,不能2次賦值,就沒辦法實現深度複製。還有一種情況,內部屬性之間是相互引用,循環參考的,此時要實現複製就非常困難。     3、深度複製需要複雜的代碼,這個沒啥好說的。
四、模式擴充
     調用者直接複製原型有個缺點,調用者的角色不明確,他需要直到要用哪個原型,原型對象和複製出來的產品之間也可能無法區分(大部分時候不用區分),所以有一種方式引入了原型管理器來管理原型,維護已有原型的清單,調用者使用時會向原型管理器發出請求,擷取原型,這樣調用者就不需要知道具體原型了,原型和複製出來的產品也可以區分了。     這個是相比其他建立型模式來說的,沒有工廠,沒有單例,沒有導演類,原型模式只需要一個產品原型,就能複製出其他產品,所以非常靈活,調用者可以在運行時動態增加和刪除產品,而不用先寫一堆工廠,單例,建造者這樣的類。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.