引言說實話,我看過GoF《Design Patterns》,也曾深深的被李建忠《設計模式》系列Webcast吸引。但是還沒有見過“Double Dispatch模式”。的確GoF提及的設計模式只是最初對設計模式的系統介紹,它不可能涵蓋所有的模式。另外隨著時間的流逝,技術日新月異的變化,技術大牛們又總...
引言
說實話,我看過GoF《Design Patterns》,也曾深深的被李建忠《設計模式》系列Webcast吸引。但是還沒有見過“Double Dispatch模式”。的確GoF提及的設計模式只是最初對設計模式的系統介紹,它不可能涵蓋所有的模式。另外隨著時間的流逝,技術日新月異的變化,技術大牛們又總結出了許多新的模式。
今天所介紹的Double Dispatch模式,從時間上來看,已不是新的設計模式;但對於只看過GoF設計模式的技術同仁來說,也算是一個新的設計模式。
什麼是DoubleDispatch?
對,沒有“模式”二字。從字面翻譯來看,網上好多人翻譯為雙分發,雙分派。Wiki上對Double Dispatch的解釋:
In software engineering, double dispatch is a special form of multiple dispatch, and a mechanism that dispatches a function call to different concrete functions depending on the runtime types of two objects involved in the call. In most object-oriented systems, the concrete function that is called from a function call in the code depends on the dynamic type of a single object and therefore they are known as single dispatch calls, or simply virtual function calls.
大意:
在軟體工程中,Double Dispatch是一種特殊形式的Multiple Dispatch,也是根據於兩個對象的運行時類型來調用的其相應具體類(不是基類)方法的一種機制。在大多數面向對象的系統中,在代碼(程式)中的一個函數調用具體類的方法都取決於單個對象的動態類型(運行時的類型),(它們一般)被稱為Single Dispath calls,或只是虛擬函數調用。
不難看出一次虛函數的調用叫做Single Dispath ,那麼Double Dispatch應該就是兩次虛函數的調用啦。
更進一步說就是一次通過動態類型(運行時類型)調用相應子類真實類型的方法函數,就稱為一次Dispath。那麼以此類推,需要兩次通過運行時類型調用相應類型的方法函數,則稱為Double Dispatch。
舉例說明:
Single Dispatch 實例:
DoubDispatch 實例:
為啥要搞Double Dispatch?
輸出結果
怎麼沒有輸出“Dog Type”和“Mammals Type”呢?不對呀!!
怎麼解決?
用Dynamic來解決
通過查閱關於函數重載決議相關的說明我們可以瞭解到:
重載是在編譯時就決定了,所以無法在運行時動態決定。重寫才是動態運行時決定的。
輸出結果:
這樣的解決雖然看起來解決了問題?但我不通過Double Dispatch 來實現的。只是通過了Dynamic。
用Vistor 模式來解決
總結
C# 現在引入Dynamic 來支持“Double Dispatch”,但我們應該清楚到底為什麼要用這個關鍵字.
如果沒有這個關鍵字,C#又是如何支持“Dobule Dispatch”的,這就是本篇所講的目的。
更多關於Vistor內容,大家可自行百度谷歌。
後續我想寫一篇關於Vistor的博客,還請大家多多支持!
參考
GoF著作中未提到的設計模式(4):Double Dispatch
關於雙分派(Double Dispatch)的一點探討(案例講的很透徹,C++的代碼)
Acyclic Visitor模式:http://www.objectmentor.com/resources/articles/acv.pdf
Hierachical Visitor Pattern模式:http://en.wikipedia.org/wiki/Hierarchical_visitor_pattern