編程旅途是漫長遙遠的,在不同時刻有不同的感悟,本文會一直更新下去,
思考總結
思考問題
如果沒有原型模式,當我們復制復雜物件,在新建相同類的物件,遍歷原始物件中的所有成員變數并將成員變數復制到新物件的程序中會產生什么問題?
-
并非所有物件都能通過這種方式復制,因為物件可能擁有私有成員變數,它們在物件本身以外是不可見的,
-
因為你必須知道物件所屬的類才能創建復制品,所以代碼必須依賴該類,有時你只知道物件所實作的介面,而不知道其所屬的具體類,比如可向方法的某個引數傳入實作了某個介面的任何物件,
什么是原型模式
原型是一種創建型設計模式,使你能夠復制已有物件,而又無需使代碼依賴它們所屬的類,
原型模式:用原型實體指定創建物件的種類,并且通過拷貝這些原型創建新的物件,

含義:
- 原型模式將克隆程序委派給被克隆的實際物件,模式為所有支持克隆的物件宣告了一個通用介面,該介面讓你能夠克隆物件,同時又無需將代碼和物件所屬類耦合,你甚至可以復制私有成員變數,因為絕大部分編程語言都允許物件訪問其自身的私有成員變數,支持克隆的物件即為原型,
何時使用:
- 如果你需要復制一些物件,同時又希望代碼獨立于這些物件所屬的具體類,可以使用原型模式,通常出現在代碼需要處理第三方代碼通過介面傳遞過來的物件時,即使不考慮代碼耦合的情況,你的代碼也不能依賴這些物件所屬的具體類,因為你不知道它們的具體 資訊,
- 如果子類的區別僅在于其物件的初始化方式,那么你可以使用該模式來減少子類的數量,別人創建這些子類的目的可能 是為了創建特定型別的物件,
- 當要實體化的類是在運行時刻指定時,例如,通過動態裝載,
- 當一個類的實體只能有幾個不同狀態組合中的一種時,建立一系列預生成的、各種型別的物件作為原型并克隆它們可能比每次用合適的狀態手工實體化該類更方便一些,
- 當你的物件有幾十個成員變數和幾百種型別時,對其進行克隆甚至可以代替子類的構造,創建一系列不同型別的物件并用不同的方式對其進行配置,如果所需物件與預先配置的物件相同,那么你只需克隆原型即可,無需新建一個物件,
實作方法:
- 創建原型介面,并在其中宣告克隆方法,如果你已有類層次結構,則只需在其所有類中添加該方法即可,
- 原型類必須另行定義一個以該類物件為引數的建構式,建構式必須復制引數物件中的所有成員變數值到新建物體中, 如果你需要修改子類,則必須呼叫父類建構式,讓父類復制其私有成員變數值,
- 每個類都必須顯式重寫克隆方法并使 用自身類名呼叫 new 運算子,
- 你還可以創建一個中心化原型注冊表,用于存盤常用原型,
- 你可以新建一個工廠類來實作注冊表,或者在原型基類中添加一個獲取原型的靜態方法,該方法必須能夠根據客戶端代 碼設定的條件進行搜索,搜索條件可以是簡單的字串,或 者是一組復雜的搜索引數,找到合適的原型后,注冊表應對原型進行克隆,并將復制生成的物件回傳給客戶端,最后還要將對子類建構式的直接呼叫替換為對原型注冊表工廠方法的呼叫,
應用實體:
- 細胞分裂
優點:
- 你可以克隆物件,而無需與它們所屬的具體類相耦合,
- 你可以克隆預生成原型,避免反復運行初始化代碼,性能提高, 逃避建構式的約束,
- 你可以更方便地生成復雜物件,
- 你可以用繼承以外的方式來處理復雜物件的不同配置,
缺點:
- 克隆包含回圈參考的復雜物件可能會非常麻煩,
- 必須實作 Cloneable 介面,
使用場景:
- 資源優化場景, 類初始化需要消化非常多的資源,這個資源包括資料、硬體資源等, 性能和安全要求的場景,
- 通過 new 產生一個物件需要非常繁瑣的資料準備或訪問權限,則可以使用原型模式,
- 一個物件多個修改者的場景, 一個物件需要提供給其他物件訪問,而且各個呼叫者可能都需要修改其值時,可以考慮使用原型模式拷貝多個物件供呼叫者使用,
- 在實際專案中,原型模式很少單獨出現,一般是和工廠方法模式一起出現,通過 clone 的方法創建一個物件,然后由工廠方法提供給呼叫者,
與其他模式的關系:
- 原型可用于保存命令的歷史記錄,
- 大量使用組合和裝飾的設計通常可從對于原型的使用中獲益, 你可以通過該模式來復制復雜結構,而非從零開始重新構造,
- 原型并不基于繼承,因此沒有繼承的缺點,另一方面,原型需要對被復制物件進行復雜的初始化, 工廠方法基于繼承, 但是它不需要初始化步驟,
- 有時候原型可以作為備忘錄的一個簡化版本,其條件是你需要在歷史記錄中存盤的物件的狀態比較簡單,不需要鏈接其 他外部資源,或者鏈接可以方便地重建,
- 抽象工廠、生成器和原型都可以用單例來實作,
注意事項:原型模式分淺拷貝和深拷貝,在設計原型模式的時候需要著重考慮,
參考資料
- 《Go語言核心編程》李文塔
- 《Go語言高級編程》柴樹彬、曹春輝
- 《大話設計模式》程杰
- 《深入設計模式》亞歷山大·什韋茨
- 菜鳥教程
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/509059.html
標籤:設計模式
下一篇:設計模式之備忘錄模式
