面向對象設計模式縱橫談:Prototype 原型模式(筆記記錄)

   有一段時間沒寫東西了,今天繼續把沒寫完的設計模式寫完,今天這堂課是建立型設計模式的最後一堂課,原型設計模式,它一樣也是解決了對象在建立的過程當中的解耦合的狀況,面對變化使代碼更穩定,更準確的說是使建立對象的主業務邏輯更穩定。好了,咱們繼續。咱們縣討論一下依賴關係。設計模式

   依賴關係的倒置

   抽象不該該依賴於實現細節,實現細節應該依賴於抽象。

  -抽象A直接依賴於實現細節b,實現細節b就相似我要吃米飯,上午可能要吃米飯,下午就可能要吃炸醬麪,每一個人習慣不一樣,這個是常常變化的。對於軟件設計來講,咱們可能設計一個我要吃飯的接口,具體吃什麼,是米飯仍是炸醬麪,經過其餘方法實現,這樣就保證了軟件系統接口的穩定性。抽象A和實現細節b的關係就像【人-----》吃米飯】,這樣的關係很差,軟件易變化,就是容易改代碼。這樣的關係應該改爲【人------》吃飯】,整個環境就安靜了,穩定了。



-抽象A依賴於抽象B,實現細節b依賴於抽象B,這幅圖就是【人-----》吃飯】,具體吃什麼飯之後再說。



 
動機(Motivation)

在軟件系統中,常常面臨着「某些結構複雜的對象」的建立工做;因爲需求的變化,這些對象常常面臨着劇烈的變化,可是它們卻擁有比較穩定一致的接口。

如何應對這種變化?如何向「客戶程序(使用這些對象的程序)」隔離出「這些易變對象」,從而使得「依賴這些易變對象的客戶程序」不隨着需求改變而改變?
 

意圖(Intent)

使用原型實例指定建立對象的種類,而後經過拷貝這些原型來建立新的對象——《設計模式》GoF
這是原話,很精煉,咱們看看類圖吧,更明確一點。

結構(Structure)

數組

咱們看了這麼多設計模式的類圖了,你們應該也總結出一些經驗來,客戶端依賴的都是抽象的接口,【這個接口不是C#語言裏面的Interface或者抽象類】,原型模式裏面有一個抽象原型對象,他是穩定的,經過自身的克隆實現對象的建立。

例說Prototype應用,代碼截圖以下:



上面的代碼,GameSystem依賴於具體的new的對象,若是面臨對象變化,例如若是要增長一個新的角色,就要從新修改編譯了。對此,咱們就能夠用工廠方法來改變,可是,對於每個類型都要寫一個工廠類,比較繁瑣。咱們也能夠用抽象工廠方法,建立一組對象,若是這樣作,這個實現有點笨重,若是增長一個角色面臨抽象工廠的劇烈變化。因此咱們這裏選擇使用原型模式。

先把GameSystem裏用到的類型換爲抽象類型,這些抽象的類型是面向客戶端的,或者說是客戶使用的接口。





再將須要new的具體對象用參數傳入,這樣在GameSystem這個客戶程序裏面就只依賴於抽象而不依賴於具體了。具體的NormalActorA、FlyActorA等都不出如今GameSystem中。



應用程序



給抽象類增長Clone抽象方法



給具體類實現Clone方法



但有一點要注意,MemberwiseClone方法只是一種淺拷貝,它只能拷貝全部的值類型和String,若是是引用類型(例如數組),它就會只拷貝引用,而不會從新建立對象,例如對數組,就只會拷貝數組的地址。

以下圖,左邊是棧,右邊是堆,(.NET的類都是在堆上)



若是想深拷貝,除了用笨辦法,還能夠用序列化的方式來作。首先須要把類標記爲可序列化,而後將類序列化到內存,再把內存中的類反序列化,反序列化獲得的對象和原來的對象必定是深拷貝。



在對於結構中的圖,能夠對應爲:Client就是GameSystem,Operation方法就是Run。Prototype抽象類就對應NormalActor,ConcretePrototype即NormalActorA。

 

Prototype模式的幾個要點

Prototype模式一樣用於隔離類對象的使用者和具體類型(易變類)之間的耦合關係,它一樣要求這些「易變類」擁有「穩定的接口」。

Prototype模式對於「如何建立易變類的實體對象」(建立型模式除了Singleton模式之外,都是用於解決建立易變類的實體對象的問題的)採用「原型克隆」的方法來作,它使得咱們能夠很是靈活地動態建立「擁有某些穩定接口」的新對象——所需工做僅僅是註冊一個新類的對象(即原型),而後在任何須要的地方不斷地Clone。

Prototype模式中的Clone方法能夠利用.NET中的Object類的MemberwiseClone()方法或者序列化來實現深拷貝。

 
有關建立型模式的討論

Singleton模式解決的是實體對象個數的問題。除了Singleton以外,其餘建立型模式解決的都是new所帶來的耦合關係。

Factory Method,Abstract Factory,Builder都須要一個額外的工廠類來負責實例化「易變對象」,而Prototype則是經過原型(一個特殊的工廠類)來克隆「易變對象」。(其實原型就是一個特殊的工廠類,它只是把工廠和實體對象耦合在一塊兒了)

若是遇到「易變類」,起初的設計一般從Factory Method開始,當遇到更多的複雜變化時,再考慮重構爲其餘三種工廠模式(Abstract Factory,Builder,Prototype)。

 
      通常來講,若是可使用Factory Method,那麼必定可使用Prototype。可是Prototype的使用狀況通常是在類比較容易克隆的條件之上,若是是每一個類實現比較簡單,均可以只用實現MemberwiseClone,沒有引用類型的深拷貝,那麼就更適合了。Prototype若是要實現深拷貝,還須要在每一個要克隆的類上加序列化標籤,這點複雜度要考慮進程序中。ui

相關文章
相關標籤/搜索