1. 程式人生 > >面向對象五大設計原則

面向對象五大設計原則

gof 黃河 文件 容易 style 繼承 單一職責原則 原來 幫助

以前一直認為程序中的類有使用到封裝繼承多態就是面向對象設計,其實不然

封裝,繼承,多態只是面向對象的三大特性,但是在設計程序的時候並不是說類的結構使用到了(或是體現出了)這三個特性就是面向對象,

其實真正的面向對象設計是要符合下面的五大原則,

面向對象的五大基本原則
單一職責原則(SRP)
開放封閉原則(OCP)
裏氏替換原則(LSP)
依賴倒置原則(DIP)
接口隔離原則(ISP)

單一職責原則(SRP)

? 一個類應該有一個職責,僅有一個引起它變化的原因(最簡單,最容易理解卻最不容易做到的一個設計原則)
T類負責兩個不同的職責:P1、P2. 當由於職責P1發生變化時有可能導致原本運行的P2功能發生故障.也就是說P1,P2被耦合在了一起,這種耦合會導致脆弱的設計並影響復用性。

開放封閉原則(OCP)

? 既開放又封閉,對擴展是開放的,對更改是封閉的!

? 擴展即擴展現行的模塊,當我們軟件的實際應用發生改變時,出現新的需求,就需要我們對模塊進行擴展,使其能夠滿足新的需求!

更改封閉即是在我們對模塊進行擴展時,勿需對源有程序代碼和DLL進行修改或重新編譯文件

這個原則對我們在設計類的時候很有幫助,堅持這個原則就必須盡量考慮接口封裝,抽象機制和多態技術!
例如:設計一個加法運算器給客戶,在設計之初 ,我們應該 將 一個運算的接口綁定給用戶而後將具體的加法運算實現 運算的接口而不應該直接將加法拋給用戶。如果用接口實現,在以後用戶想進行減法運算時我們只需要再編寫減法運算來實現運算的接口,而不必對原來的代碼做出修改。從而實現對擴展開放,對修改關閉。

裏氏替換原則(LSP)

? 子類可以替換父類並且出現在父類能夠出現的任何地方

? 這個原則也是在貫徹GOF倡導的面向接口編程!
在這個原則中父類應盡可能使用接口或者抽象類來實現!

子類通過實現了父類接口,能夠替父類的使用地方!
通過這個原則,我們客戶端在使用父類接口的時候,通過子類實現!
意思就是說我們依賴父類接口,在客戶端聲明一個父類接口,通過其子類來實現
這個時候就要求子類必須能夠替換父類所出現的任何地方,這樣做的好處就是,在根據新要求擴展父類接口的新子類的時候而不影響當前客戶端的使用!
鴕鳥非鳥: 如果以翅膀羽毛來區分鳥,那麽顯然鴕鳥是屬於鳥的,是鳥它就應該有行為是飛也必然有飛行速度,而我們知道鴕鳥是不會飛的所以我們設置鴕鳥的飛行速度為0。

當客戶想要測量鳥類飛躍黃河所需要的速度時 ,那麽便會出現問題,由於鴕鳥的飛行速度為0,就會有除數出現0的情況。

面向對象的設計關註的是對象的行為,只有行為上一致的對象才能抽象成一個類,我們通常所說的繼承是以 “ is a ” 為關系的實際上只關註屬性的繼承。而我們如果以飛這個行為來劃分,鴕鳥顯然不是鳥。

硬要以鴕鳥來繼承鳥,實際上對於飛這個行為鴕鳥是無法覆蓋父類的。

依賴倒置原則(DIP)

? 高層模塊不應該依賴於低層模塊,二者都應該依賴於抽象,抽象不應該依賴於細節,細節應該依賴於抽象。

例如 在ATM機取錢的時候,ATM機屬於高層,我們手上的銀行卡屬於低層,ATM內只有普通銀行卡共有的規格是一個抽象的接口,而不是存儲各種銀行卡的信息來進行判斷。當某一種銀行卡改變時我們不需要對ATM機做出改變,因為銀行卡這個接口是不變的。從而增強了代碼的復用性

ISP 接口隔離原則

? 這個原則的意思是:使用多個專門的接口比使用單個接口要好的多!

一個類對於一個類的依賴是建立在最小的接口上的,客戶端不應該依賴於他不需要的接口。也就是說不應該強迫客戶依賴他們不需要的方法。

例如: 對於公司的員工要工作的方法、吃飯的方法。我們用對象來實例化員工接口顯然沒有問題。但如果公司引進機器人來工作,若去實現員工的接口顯然是有問題的,當然我們可以設置虛值來填補。但難免不會出錯。

所以說員工這個接口是需要分離的。

而在實例化的時候我們可以實現多個接口,同樣會達到目的。

面向對象五大設計原則