在面向對象設計方法中有很多值得提倡的方法,這些方法可以為我們的設計帶來很大的靈活性,可復用性。
其中一個原則就是“針對接口編程,而不是針對實現編程”
這個原則帶來的好處有以下幾點:
Client不必知道其使用對象的具體所屬類。
Client無需知道特定類,只需知道他們所期望的接口。
一個對象可以很容易地被(實現了相同接口的)的另一個對象所替換。
對象間的連接不必硬綁定(hardwire)到一個具體類的對象上,因此增加了靈活性。
松散藕合(loosens coupling)。
增加了重用的可能性。提高了(對象)組合的機率,因為被包含對象可以是任何實現了一個指定接口的類。
在實現上:
C++通過繼承純虛類來實現接口繼承。
Java對接口繼承具有單獨的語言構造方式-Java接口。
但從辯證法的角度看,事物總有利有弊?!搬槍涌诰幊獭庇腥缟现T多好處,確不可避免的帶來設計的復雜性。特別對于沒有豐富經驗的設計人員。
其中令我比較困惑的地方是:
要想針對接口編程,就必然要最大化接口類,使包括所有子類的方法,這樣我們才能利用多態性用接口類來一致的操作子類。但這會帶來以下幾點不足。
違反面各對象的另一個原則,這個原則是:一個類只能定義那些對它的子類有意義的操作。
接口類包括了并不是對每一個子類都有意義的方法,使接口類臃腫,難以理解。
從父類繼承的無用方法,如何處理。
舉個例子來說。我們要實現這樣一個功能模塊。一個TreeView上有各種節點。我們對這樣的一個Tree 的節點操作。比如復制,剪切,粘貼,重命名,查看屬性、設置它的圖標,添加到樹節點上等等。每種節點的相同操作(比如復制)的實現是不同的。
你會怎么設計它:
在C++中我會這樣做。
我會將每種結點實現成一個類。以實現各自的相關操作(比如復制,粘貼),這些類都繼承至一個純虛的父類,在這個父類中以虛方法的方式聲名子類實現我的相關方法,這樣做的好處是當你從Tree中取出一個節點時,你不必關心這個節點是什么類實現的,你只需要以純虛的父類指針操作它就可以了,這樣就實現了接口繼承的所帶來的優點。
但是,如果并不是每個節點都支持所有的方法,比如有些節點不允許復制,有些節點不允許重命名等,那么從父類繼承的聲名如何處理,實現成一個空方法么?還是不將這樣的方法放到父類中?如果不放到父類中,就沒辦法以統一的方法操作所有的子類了!
(T007)
原文轉自:http://www.anti-gravitydesign.com