淺談java中OO的概念和設(shè)計原則(必看)
一.OO(面向?qū)ο?的設(shè)計基礎(chǔ)
面向?qū)ο?OO):就是基于對象概念,以對象為中心,以類和繼承為構(gòu)造機制,充分利用接口和多態(tài)提供靈活性,來認識、理解、刻劃客觀世界和設(shè)計、構(gòu)建相應的軟件系統(tǒng)。面向?qū)ο蟮奶卣鳎弘m然各種面向?qū)ο缶幊陶Z言相互有別,但都能看到它們對面向?qū)ο蠡咎卣鞯闹С郑?/p>
即 “抽象、封裝、繼承、多態(tài)” :
– 抽象,先不考慮細節(jié)
– 封裝,隱藏內(nèi)部實現(xiàn)
– 繼承,復用現(xiàn)有代碼
– 多態(tài),改寫對象行為
面向?qū)ο笤O(shè)計模式:是“好的面向?qū)ο笤O(shè)計”,所謂“好的面向?qū)ο笤O(shè)計”是那些可以滿足“應對變化,提高復用”的設(shè)計。面向?qū)ο笤O(shè)計模式描述的是軟件設(shè)計,因此它是獨立于編程 語言的,但是面向?qū)ο笤O(shè)計模式的最終實現(xiàn)仍然要使用面向?qū)ο缶幊陶Z言來表達。面向?qū)ο笤O(shè)計模式不像算法技巧,可以照搬照用,它是建立在對“面向?qū)ο蟆奔?熟、深入的理解的基礎(chǔ)上的經(jīng)驗性認識。
上邊就見大的描述一下面向?qū)ο蠛驮O(shè)計模式的概念和關(guān)系。我們進行設(shè)計的時候,就是充 分的理解和利用OO的四個基本的特征來展開設(shè)計,所以大家必須在進行設(shè)計前,要熟悉和掌握面向?qū)ο蟮募夹g(shù),在這就不詳細介紹了,而對于設(shè)計模式是給我們提供了設(shè)計時的參考模型,而掌握面向?qū)ο笤O(shè)計模式的前提是首先掌握“面向?qū)ο蟆奔夹g(shù)。
二.OO(面向?qū)ο?的設(shè)計目標
※可擴展性Extensibility:有了新的需求,新的性能可以容易添加到系統(tǒng)中,不影響現(xiàn)有的性能,也不會帶來新的缺陷。
※可修改性Flexibility:系統(tǒng)一部分的代碼要修改時不會破壞系統(tǒng)的現(xiàn)有結(jié)構(gòu),也不會影響到其它的部分。
※可替換性Pluggability:可以將系統(tǒng)中的某些代碼替換為相同接口的其它類,不會影響到系統(tǒng)。
三.OO設(shè)計的5大原則及其之間的關(guān)系
3.1 OO設(shè)計原則的總結(jié)
※單一職責原則:就一個類而言,應該僅有一個引起它變化的原因。單一是一個類的優(yōu)良設(shè)計。交雜不清的職責將使得代碼看起來特別別扭牽一發(fā)而動全身,有失美感和必然導致丑陋的系統(tǒng)錯誤風險。
※開放封閉原則:是說軟件實體(類、模塊、函數(shù)等等)應該可以擴展但不可修改。實現(xiàn)開開放封閉原則的核心思想就是對抽象編程,而不對具體編程,因為抽象相對穩(wěn)定。讓類依賴于固定的抽象,所以修改就是封閉的;而通過面向?qū)ο蟮睦^承和多態(tài)機制,又可以實現(xiàn)對抽象類的繼承,通過覆寫其方法來改變固有行為,實現(xiàn)新的拓展方法,所以就是開放的。“需求總是變化”沒有不變的軟件,所以就需要用封閉開放原則來封閉變化滿足需求,同時還能保持軟件內(nèi)部的封裝體系穩(wěn)定,不被需求的變化影響。
※依賴倒置原則:依賴抽象,不要依賴具體。抽 象的穩(wěn)定性決定了系統(tǒng)的穩(wěn)定性,因為抽象是不變的,依賴于抽象是面向?qū)ο笤O(shè)計的精髓,也是依賴倒置原則的核心。依賴于抽象是一個通用的原則,而某些時候依 賴于細節(jié)則是在所難免的,必須權(quán)衡在抽象和具體之間的取舍,方法不是一層不變的。依賴于抽象,就是對接口編程,不要對實現(xiàn)編程。
※里氏代換原則:子類型必須能夠替換到他們的父類型。Liskov 替換原則,主要著眼于對抽象和多態(tài)建立在繼承的基礎(chǔ)上,因此只有遵循了Liskov替換原則,才能保證繼承復用是可靠地。實現(xiàn)的方法是面向接口編程:將公 共部分抽象為基類接口或抽象類,通過ExtractAbstractClass,在子類中通過覆寫父類的方法實現(xiàn)新的方式支持同樣的職責。Liskov替 換原則能夠保證系統(tǒng)具有良好的拓展性,同時實現(xiàn)基于多態(tài)的抽象機制,能夠減少代碼冗余,避免運行期的類型判別。
※接口隔離原則: 多個和客戶相關(guān)的接口要好于一個通用接口。分離的手段主要有以下兩種:1、委托分離,通過增加一個新的類型來委托客戶的請求,隔離客戶和接口的直接依賴,但是會增加系統(tǒng)的開銷。2、多重繼承分離,通過接口多繼承來實現(xiàn)客戶的需求,這種方式是較好的。
下邊是前面沒有提到過的兩個原則,也是設(shè)計時要考慮的重要原則。
※迪米特法則:不相互直接通信的類之間,不要直接發(fā)生相互作用。如果兩個類不必彼此直接通信,那么這兩個類就不應當發(fā)生直接的相互作用。如果一個類需要調(diào)用領(lǐng)一個類的某個方法話,可以通過第三者轉(zhuǎn)發(fā)這個調(diào)用。迪米特法則首先強調(diào)的前提是在類的設(shè)計上,每一類都應當盡量降低成員的訪問權(quán)限。它的根本思想是強調(diào)類之間的松耦合。
※合成/聚合復用原則:盡量使用合成/聚合,盡量不要使用繼承。合 成(Composition)和聚合(Aggregation)都是關(guān)聯(lián)的特殊種類,聚合表示一種弱的擁有關(guān)系;合成這是一種強的擁有關(guān)系,體現(xiàn)了嚴格的部分和整體的關(guān)系,部分和整體的生命周期一樣。優(yōu)先使用合成或聚合原則將有助于保持每個類被封裝,并被集中在單個任務上。這樣類和類繼承層次會保持較小規(guī) 模,并且不太可能增長為不可控制的龐然大物
3.2 OO設(shè)計原則之間的關(guān)系
1. 實現(xiàn)“開-閉”原則(OCP)的關(guān)鍵步驟是抽象化?;惻c子類之間的繼承關(guān)系就是抽象化的體現(xiàn)。因此里氏代換原則是對實現(xiàn)抽象化的具體步驟的規(guī)范。違反里氏代換原則意味著違反了“開-閉”原則,反之未必。
2. “開-閉”原則與依賴倒轉(zhuǎn)原則(DIP)是目標和手段的關(guān)系。如果說開閉原則是目標,依賴倒轉(zhuǎn)原則是到達"開閉"原則的手段。如果要達到最好的"開閉"原則,就要盡量的遵守依賴倒轉(zhuǎn)原則,依賴倒轉(zhuǎn)原則是對"抽象化"的最好規(guī)范。
3. 里氏代換原則(LSP)是依賴倒轉(zhuǎn)原則的基礎(chǔ),依賴倒轉(zhuǎn)原則是里氏代換原則的重要補充。
4. 接口分離原則(ISP)也是確?!伴_-閉”原則的一個重要手段。
5. 對于單一職責原則(SRP),個人認為盡量做到為好,職責越單一,“開-閉”和里氏代換越容易實現(xiàn)。
四.OO設(shè)計原則和目標的關(guān)系
1.可擴展性Extensibility :允許一個具有同樣接口的新類替代舊類,是對抽象接口的復用??蛻舳艘蕾囉诔橄蠼涌冢皇且粋€具體實現(xiàn)類,使得這個具體類可以被別的具體類替換,而不影響客戶端。以下原則實現(xiàn)可擴展性。
※開/閉原則
※里氏替換原則
※依賴倒轉(zhuǎn)原則
※合成/聚合復用原則
2.可修改性Flexibility:模塊相對獨立,通信盡可能少。這樣當一個模塊修改時,對別的模塊的影響很小。
以下原則實現(xiàn)可修改性。
※開/閉原則
※迪米特法則
※接口隔離原則
3、可替換性Pluggability:當一部分不再滿足需要時,可以將舊的部分拔出,新的部分插入。
以下原則實現(xiàn)可替換性。
※開/閉原則
※里氏代換原則
※依賴倒轉(zhuǎn)原則
※合成/聚合復用原則
五.OO(面向?qū)ο?的設(shè)計過程
1. 分析式樣,進行機能分類。
2. 根據(jù)機能進行類的抽象。
※ 類的抽象 - 在這里步里,我們可以根據(jù) “單一職責原則”,進行類的具體抽象。盡量做到,類的功能單一和清晰化。
※ 封裝變化點– 使用封裝來創(chuàng)建對象之間的分界層,讓設(shè)計者可以在分界層的一側(cè)進行修改,而不會對另一側(cè)產(chǎn)生不良的影響,從而實現(xiàn)層次間的松耦合。
3. 設(shè)計抽象基類和接口類。
※ 在進行基本的基類的抽象和接口定義時,要遵照“接口分離原則”進行接口的抽象。
※ 在設(shè)計接口和基類時,不要總是關(guān)注細節(jié),要記住針對接口編程,而不是針對實現(xiàn)編程。
※ 對于抽象的基類和派生類之間要做到“里氏替換原則”的要求。
4.確定類間的耦合關(guān)系。
4.1 決定耦合的程度的依據(jù)何在呢?
※ 簡單的說,就是根據(jù)需求的穩(wěn)定性,來決定耦合的程度。
※ 對于穩(wěn)定性高的需求,不容易發(fā)生變化的需求,我們完全可以把各類設(shè)計成緊耦合的,因為這樣可以提高效率,而且我們還可以使用一些更好的技術(shù)來提高效率或簡化代碼。
※ 如果需求極有可能變化,我們就需要充分的考慮類之間的耦合問題,我們可以想出各種各樣的辦法來降低耦合程度,但是歸納起來,不外乎增加抽象的層次來隔離不同的類,這個抽象層次可以是抽象的類、具體的類,也可以是接口,或是一組的類。我們可以用一句話來概括降低耦合度的思想:"針對接 口編程,而不是針對實現(xiàn)編程。
※ 在決定類的耦合關(guān)系時,盡量考慮“迪米特法則”和“合成/聚合復用原則”。
4.2 怎樣做到依賴倒轉(zhuǎn)?
※ 以抽象方式耦合是依賴倒轉(zhuǎn)原則的關(guān)鍵。抽象耦合關(guān)系總要涉及具體類從抽象類繼承,并且需要保證在任何引用到基類的地方都可以改換成其子類,因此,里氏代換原則是依賴倒轉(zhuǎn)原則的基礎(chǔ)。
※ 依賴于抽象:建議不依賴于具體類,即程序中所有的依賴關(guān)系都應該終止于抽象類或者接口。盡量做到:
(1)任何變量都不應該持有一個指向具體類的指針或者引用。
(2)任何類都不應該從具體類派生。
(3)任何方法都不應該覆寫它的任何基類中的已經(jīng)實現(xiàn)的方法。
5.運用OO設(shè)計的5大原則來對設(shè)計進行進一步的優(yōu)化
※ 對于類的抽象和職能,是否滿足“單一職責原則”
※ 對于繼承關(guān)系和引用基類的地方,是否滿足“里氏代換原則”和“依賴倒置原則”
※ 對于接口和基類,是否“接口隔離原則”
※ 總體上是否滿足“開-閉原則”
總體上說,在面向?qū)ο笤O(shè)計時,要充分考慮設(shè)計的5大原則,但不是強求的,一味的追求滿足原則也可能會導致設(shè)計出的系統(tǒng)在性能和資源上的消耗,可以根據(jù)具體的情況來具體的分析和設(shè)計。
以上這篇淺談java中OO的概念和設(shè)計原則(必看)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot集成shiro遭遇自定義filter異常的解決
這篇文章主要介紹了springboot集成shiro遭遇自定義filter異常的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11java注解實現(xiàn)websocket服務的兩種方式
Java WebSocket是一種基于TCP協(xié)議的雙向全雙工消息傳輸技術(shù),它允許服務器和客戶端之間實時通信,具有低延遲和高效率的特點,下面這篇文章主要給大家介紹了關(guān)于java注解實現(xiàn)websocket服務的兩種方式,需要的朋友可以參考下2024-08-08Spring Boot 自定義數(shù)據(jù)源DruidDataSource代碼
這篇文章主要介紹了Spring Boot 自定義數(shù)據(jù)源DruidDataSource代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-10-10Jersey Restful接口如何獲取參數(shù)的問題
這篇文章主要介紹了Jersey Restful接口如何獲取參數(shù)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06