面向對象的設計原則

面向對象開發方法比我都老了,今天就不談經的背景與基本概念了。引出幾個設計原則,給大家和自己都提個醒。

l  單一職責原則(SRP

一個類,應該僅有一個引起它變化的原因。

SRP是我認爲最基本,而我們又最經常違反的原則。簡單理解,就是每個類的功能都是功能單一的。而我們在編程的時候,會很自然地爲一個類加入各種各樣的功能,比如編寫一個窗體時,爲了方便會把各代碼,像業務邏輯算法、數據庫詢問的SQL語句都寫到這個類中,這意味着,無論任何需求添加或修改,都要更改這個窗體類。這樣維護麻煩,複用性也極差(我也經常幹這事)。正確做法應該是讓窗體類只負責顯示,邏輯算法和數據庫詢問應該由其它類完成,也就是我們常說的實現邏輯和界面的分離。

l  開放封閉原則(OCP

一個模塊(或類)應該是對擴展是開放的,而對修改是封閉的。

OCP是所有面向對象原則的核心,其它很多原則都是爲實現此原則服務的。在面向對象設計中,這個原則我們在發生變化時,不要修改類型的源代碼,每個類型都應該是固定的,對修改是關閉的。發生變化時,要通過添加新代碼來增強現有類型的行爲。實際中就意味着使用組合或繼承了。當前符合OCP最好的方式就是提供一個固定的接口,讓可能發生變化的類實現該接口,這也遵守了面象對象設計的基於接口編程原則。

l  里氏替換原則(LSP

子類應該可以代替其基類使用。

我們如何去度量繼承關係的質量?LiskovN年提出了一個關於繼承的原則:“繼承必須確保基類所擁有的性質在子類中仍然成立。”,這就是里氏替換原則。這比較容易理解,就是說父類(父親)能做的事,子類(兒子)也能要能做,並在某種情況下子類都安全地替換其基類使用(做好兒子不容易的)。貌似都可以吧?未必!如基類的虛方法詢問了私有成員,子類重寫時就無法實現本原則。不滿足LSP的類會讓調用都無法滿足OCP

l  依賴倒置原則(DIP

高層模塊不應依賴低層模塊,兩者均該依賴抽象。

抽象不應依賴細節,細節應該依賴抽象。

爲了使得常用功能代碼可以利用,我們一般會寫很多的函數庫,當我們項目時,只需調用這些低層的函數,這也叫高層模塊依賴低塊模型。如果低層模塊發生變化時,依賴這些低層函數的其它模型就麻煩了。而如是不管是高層模塊還是低層模塊,它們都依賴於抽象類還接口,只要接口是穩定,那麼誰也不怕受到影響。再回頭看看里氏替換原則(LSP)和開放封閉原則(OCP),就能更深入理解。

l  接口隔離原則(ISP

使用多個專門的接口比使用單一的總接口要好。

一個接口是一個角色,不應將不同角色都交給一個接口,這將導致接口的臃腫。一個類對另一個的依賴是建立在最少的接口上,被調用的類只提供調用類需要的方法,屏蔽不需要的方法。暴露不必要的方法,就誘導調用類使用它不關心的方法,更會導致調用類使用這些不關心的方法而造成不必要的改變。通俗一點講,接口儘量細化,同時接口中的方法儘量少,而一個類實現多個接口。讀者回頭一看,這不是和單一職責原則(SRP)很相似嗎?其實不然,SPR是要求類和接口的職責單一,注重的是職責,是多邏輯上劃分的。而ISP則要求接口的方法儘量少,注重對接口依賴的隔離。運用本原則,一定要適度,接口設計的過大或過細都不好。

 

面向對象有很多設計原則,瞭解這此原則對我們做設計和編程有極大的幫助。本人雖對這些原則早有耳聞,但項目開發中也經常違反了不少,間接導致代碼維護成本高、靈活性低。特記一文,告示同行們引起注意,也警惕自己。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章