C#基礎系列:委託和設計模式(2)

發表於2016-03-05

前言:這篇打算從設計模式的角度去解析下委託的使用。我們知道使用委託可以實現物件行為(方法)的動態繫結,從而提高設計的靈活性。上次說過,方法可以理解為委託的例項,站在方法的層面,委託例項的一個非常有用的特性是它既不知道,也不關心其封裝方法所屬類的詳細資訊,對它來說最重要的是這些方法與該委託的引數和返回值的相容性。即只要方法的返回型別和參數列是相同的,則方法與委託型別相容,方法的名稱及方法所屬類等資訊委託是不關心的。有一定程式設計經驗的大俠們肯定都接觸過設計模式,其實設計模式大多數都是物件導向多型特性的體現,通過重寫子類方法去展現不同的設計需求,這樣看,既然是方法重寫,那麼方法的引數型別和返回值型別肯定是一致的,這是不是和委託的例項十分相似,這樣說來,我們通過多型去實現的設計模式是否可以用委託的形式去代替。博主覺得,為了更好的理解委託,可以從這方面著手試試。。。

此篇簡單抽取了幾個設計模式分別按照多型和委託的方式去實現,當然這裡的重點並不是講設計模式,而是為了使讀者更好地理解委託。所以設計模式的很多細節,本篇可能會略過。

一、簡單工廠模式:本篇就藉助計算器的例子加以說明。

1、多型實現簡單工廠模式。

程式碼應該很容易看懂,直接通過方法的重寫去實現,在此就不過多講解。

2、委託方式實現簡單工廠模式。

這裡需要定義四個實現方法Add、Subtract、Multiply、Divide,而不用在意這四個方法在哪個類下面,只要這四個方法的的引數和返回值和委託的定義保持一致即可。這也驗證了上面說的 “站在方法的層面,委託例項的一個非常有用的特性是它既不知道,也不關心其封裝方法所屬類的詳細資訊,對它來說最重要的是這些方法與該委託的引數和返回值的相容性” 。兩種方式得到的結果是相同的:

c#基礎系列

二、觀察者模式:觀察者模式最典型的場景就是訂閱者和訂閱號的場景

1、純多型方式實現觀察者模式:這種程式碼園子裡面非常多。

可以看到雖然已經很好的實現了觀察者Observer 和主題Subject之間的分離。但是Subject的內部還是有對觀察者的呼叫:

2、多型和委託實現觀察者模式。

得到結果:

c#基礎系列

這樣設計的優勢:

(1)將通知的方法Update通過委託的形式傳入主題物件。這樣主題物件Subject就完全和觀察者隔離。更好地實現了低耦合。

(2)減少了觀察者抽象類的定義。使整個設計更加精簡。

(3)如果將設計更進一步,觀察者這邊自定義delegate void ObserverDelegate()這種型別的方法。比如需要執行Update()方法之後還要記錄一個日誌的操作。如:

那麼在客戶端呼叫時只需要將Log方法以委託的形式傳入即可:

是不是顯得更靈活一點。如果是純多型的方式,由於Subject裡面指定了呼叫Update()方法,所以當需要增加Log方法的時候程式碼的改變數要大。

三、模板方法模式,這裡就以裝置採集為例來進行說明:

1、多型實現模板方法模式:

父類裡面的非abstract方法都是模板方法,也就是子類公用並且不可以重寫的方法。SpiderType1和SpiderType2是需要子類重寫的方法。模板方法模式在抽象類中定義了演算法的實現步驟,將這些步驟的實現延遲到具體子類中去實現,從而使所有子類複用了父類的程式碼,所以模板方法模式是基於繼承的一種實現程式碼複用的技術。

2、使用委託改寫後:

得到結果:

c#基礎系列

優化模板方法模式的意義:

(1)解除了子類和父類之間的繼承關係,更好地實現了物件間的低耦合。

(2)採用委託可以動態實現方法的組合,這種方式更加靈活,子類可以更加靈活的設計不同部分的方法。然後方法的數量通過params來傳遞,方法的數量沒有什麼嚴格的限制。

當然其他設計模式也可以使用委託去優化設計,博主在這裡就暫時只分享這三種模式的異同。總的來說,委託不可能代替多型去實現各種模式,但是它和多型聯合起來使用可以實現更加靈活的設計。通過這兩篇下來,不知道你是否對委託有點感覺了呢,委託這東西,重在實戰,就像游泳一樣,如果不用那麼幾次,你永遠也不可能學會。以上只是博主個人的理解,可能很多方便沒有考慮得那麼全面,希望各位園友拍磚斧正~~

本系列:

相關文章