您好,登錄后才能下訂單哦!
小編給大家分享一下c++中面向對象的設計規范,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
面向對象設計(OOD)是面向對象編程(OOP)必不可少的一個環節,只有好的設計,才能保障程序的質量。面向對象設計的主要任務就是類的設計,不少面向對象(OO)的先驅和前輩已經提出了很多關于類的設計原則,用于指導OOP,其中就包括類設計的五項基本原則。
1.單一職責原則(Single Resposibility Principle,SRP)
專注是一個人的優良品質,同樣,單一職責也是一個類的優良設計。單一職責的核心思想:一個類只做好一件事情。
單一職責原則可以看作是高內聚、低耦合在面向對象原則上的引申。類的職責過多,容易導致類間職責依賴,提高耦合度,降低內聚性。通常意義下的單一職責,指的是類只有一種單一功能,不要為類設計過多的功能,交雜不清的功能會使代碼雜亂,提高程序開發的難度和系統出錯的概率,降低系統的可維護性。
要舉個體現單一職責原則的最常見的例子無疑就是STL中的迭代器的設計。有些人覺得容器跟迭代器的分離是不好的設計,覺得增加了復雜度,不如直接把迭代器放在容器里更為簡潔。不過很多人還是不這樣認為,因為類的數量越多并不代表就越復雜,另外迭代器如果放到容器里面,就會暴露容器的一些內部結構,不太符合封裝的思想。還有就是可擴展性的問題,因為對容器的訪問遍歷會有多種需求,如果把迭代器隔離開來你可以不修改容器類,再定義些特制的迭代器就行了,這樣不管有什么奇怪的需求只要寫個對應的迭代器出來就行了。
2.開放封閉原則(Open Closed Principle,OCP)
開閉原則指的是開放封閉原則,即對擴展開放,對修改封閉。
所謂修改封閉,就是之前設計好的類,不要去修改。比如刪除掉一個成員函數、改變成員函數的形參列表或更改數據成員類型等。實現對修改封閉,關鍵在于抽象化。對一個事物抽象化,實質上是對一個事物進行概括、歸納、總結,將其本質特征抽象地用一個類來表示,這樣類才會相對穩定,無需更改。
所謂擴展開放,就是在不改變已存在的類的前提下可以添加很多功能。一般是通過繼承和多態來實現,如此一來,可以保持父類的原樣,只需在子類中添加些所需的新功能。
“需求總是變化的”,如果遵循開放封閉原則,合理設計就能封閉變化,使類能夠靈活的擴展所需的功能。
3.里氏替換原則(Liskov Substituion Principle,LSP)
Liskov替換原則指的是:子類可以替換父類并出現在父類能夠出現的任何地方。這個原則是Liskov于1987年提出,它同樣可以從Bertrand Meyer的DBC(Design by Contract,按契約設計)的概念推出。
C++語言機制將類的抽象與多態建立在繼承的基礎上,其實現的方法是面向接口編程:通過提取純虛類(Abstract Class),將公共部分抽象為基類接口或由子類重寫覆蓋基類方法來達到多態的目的。Liskov替換原則的作用就是為了保證繼承復用的可靠。
下面來舉個違反替換原則的特殊例子:
正方形與長方形的問題也是屬于“圓不是橢圓”這類問題。我們知道正方形是一個特殊的長方形,所以可以設計兩個類,正方形類繼承自長方形類。長方形類有兩個成員變量,分別表示長和寬,有個計算面積的成員函數。假如計算面積的方法是virtual的,這樣能實現多態。在先設定長和寬后再調用計算面積的方法。我們知道正方形是長和寬相等的,如果設定長和寬的時候不是一樣的,然后調用了正方形的面積計算公式,這樣肯定就錯了。你可能會問咋這么扯蛋啊,為啥把長和寬設成不一樣啊。很多設計思想和方法是一來為了方便,二來為了讓用戶少犯錯誤,就是不管你怎么使用都不會出錯,要出錯應該是在編譯時出錯,放置運行時出錯。如果出現上面說的情況編譯器是沒法讓你知道出錯了的。
所以一個正方形類繼承自長方形類的設計是不好的(注意的一點是你違反了Liskov替換原則并不是說就寫的代碼就會出錯,只是說設計不太合理。實際上你這樣設計代碼沒準可以正常的跑得很好呢,如果沒有出現一些特殊情況可能是一點bug也沒有,只不過設計不合理為導致一些安全隱患而已)。
4. 依賴倒置原則(Dependecy Inversion Principle,DIP)
其核心思想是:依賴于抽象。具體而言就是高層模塊不依賴于底層模塊,二者都依賴于抽象;抽象不依賴于具體,具體依賴于抽象。依賴倒置原則是對傳統過程性設計方法的“倒轉”,是高層次模塊復用及其可維護性的有效規范。
依賴一定存在于類與類、模塊與模塊之間。類與類之間產生依賴時,依賴倒置原則的理解可以描述如下:依賴就是剛開始時具體細節間互相依賴,我們將實現的細節變成抽象類,降低類間耦合度。然后有了抽象類,繼承自它的實現類也要依賴它。那倒置兩字咋理解呢? 一般情況我們是先關注細節,然后根據細節抽象出來一些概括的方法,所以按常理一般是抽象要依賴于細節的,而現在是是倒過來了,確定一個抽象類后,那些細節的實現得以抽象出來的方法為基準,變成了細節依賴于抽象了,不然你要繼承了一個抽象類,你不完全實現它的方法的話可不讓你實例化對象的啊。
當兩個模塊之間存在緊密的耦合關系時,最好的方法就是分離接口和實現:在依賴之間定義一個抽象的接口,供高層模塊調用,底層模塊實現接口的定義,從而有效控制耦合關系,達到依賴于抽象的設計目的。
依賴于抽象就是不對實現編程,而對接口編程。依賴于抽象是一個通用原則,而有些時候依賴于細節是在所難免的,我們需要根據具體情況在在抽象與具體之間進行取舍。
5.接口分離原則(Interface Segregation Principle,ISP)
該原則的核心思想是:使用多個小的專門的接口,而不要使用一個大的總接口。具體而言,接口應該是內聚的,應該避免“胖”接口。一個類對另一個類的依賴應該建立在最小的接口上,而不要強迫依賴不同的方法,這是一種接口污染。
其實簡單點的講與前面說的單一職責類似,這里的接口不是函數接口,而是一個類。C#中的有專門的接口interface,和類區分開來,而且C#中不像C++支持類的多繼承,只支持接口的多繼承,所以這里可以把接口理解成功能更小更特殊的類,一個接口可能就只要那么幾個很少的方法就OK了。
接口分離手段主要有以下兩種方式:
(1)利用委托分離接口;
(2)利用多重繼承分離接口。
6.小結
概括地講,面向對象設計原則仍然是面向對象思想的體現。例如,
(1)單一職責原則要求類只負責一件事情。接口分離原則,讓客戶只關心他們所需的接口。單一職責原則與接口分離原都體現了內聚的思想;
(2)開放封閉原則,要求類不作修改而能夠擴展功能,體現了類的封裝與繼承;
(3)Liskov替換原則,要求派生類要能夠替換基類,是對類繼承的規范;
(4)依賴倒置原則,要求類依賴于抽象,而不是實現,是抽象思想的體現。
上面五條面向對象設計原則,可以幫助我們設計出代碼易于復用、功能易于擴展、運營易于維護的程序,需要我們在實踐中遵守。
以上是c++中面向對象的設計規范的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。