文/大大大大峰哥
概述
在Java設(shè)計模式中,我們通常在設(shè)計上面需要遵循六大原則
單一職責原則
單一職責原則的定義
單一職責原則是一個類,引起它變化的原因只有一個.
該原則提出的是一個理想期望,任務(wù)對象不應(yīng)該承擔太多的職責,實現(xiàn)專注,才能保證對象的高內(nèi)聚;單一性則可以保住對象的細粒度.高內(nèi)聚與細粒度有利于對象的重用.當一個類承擔了太多的職責,會造成冗余代碼.
注意:單一職責原則不是只要求我們?yōu)轭惗x一個職責,而是提醒我們在一個類中盡量讓類負載少的職責,從而保證對象具有高內(nèi)聚與細粒度.
有時候我們在寫項目的時候,比如是一個自行車的類,我們按照自行車一般的屬性方法將這個類完善完畢,之后我們又有一個需求就是這個自行車具有某某特殊屬性或者方法的自行車.這個時候在我們沒有學習Java設(shè)計模式之前,我們會將這個特殊屬性或者方法直接寫入自行車類中.但是這個單一職責原則下,我們可以選擇重新創(chuàng)造一個類(負責擴展原有自行車功能),這樣就不會改變原有的類.這樣有什么好處:
- 降低類的復雜度
- 提高類的可讀性
- 提高代碼的可維護性和復用性
- 降低因變更而引起的風險
單一職責原則的應(yīng)用
在我們學習JavaEE的時候,JavaEE中的分層框架就體現(xiàn)了這個原則,將整個系統(tǒng)安裝職責的內(nèi)聚分為不同的層,每一層有一個主要的功能,關(guān)注事物一致.
Presentation:表現(xiàn)層
Business:業(yè)務(wù)層
persistence: 持久層
Database:數(shù)據(jù)層
用我現(xiàn)在在寫的項目來舉例,Dao包中的類就是處理一些業(yè)務(wù)邏輯,DB包中就是一些數(shù)據(jù)庫的增刪改查.

里氏替換原則
大家不要看這個名字拗口,這個其實就是教我如何正確使用繼承的.
里氏替換原則定義
如果對一個類型為S的對象o1,都有類型為T的對象o2,以S定義的所有程序P中所有的對象o1都替換成o2時,程序P行為沒有發(fā)生變化,那么類型T是類型S的子類型.
打完上面的字我內(nèi)心都是掙扎的,我感覺會有讀者大聲的說能不能說人話…其實這個里氏替換原則就是告訴我們什么是繼承,如果你知道什么是繼承,就可以直接跳過上面那段話...
注意:子類不能更改父類的訪問權(quán)限
依賴倒置原則
依賴倒置原則的定義
- 高層模塊不應(yīng)該依賴底層模型,兩者都依賴其抽象
- 抽象不依賴細節(jié)
- 細節(jié)應(yīng)該依賴抽象
我翻譯翻譯…抽象類指抽象類與接口.細節(jié)指已實現(xiàn)的類.在我們的Java項目中對該原則的表現(xiàn):
- 模塊之間的依賴是通過
抽象
產(chǎn)生,實現(xiàn)類之間不發(fā)生
直接的依賴關(guān)系. - 接口或者抽象類
不依賴
實現(xiàn)類,實現(xiàn)類依賴
于接口或者抽象類.
這個原則也就是希望我們大量使用接口和抽象類,也可以理解成"面向接口編程OOD".依賴倒置原則可以減少類間的耦合性,提高系統(tǒng)穩(wěn)定,降低并行開發(fā)引起的風險,提高可讀性和可維護性.
依賴倒置原則的應(yīng)用
上圖只有IDriver與ICar之間存在依賴關(guān)系,而實現(xiàn)類中都沒有直接關(guān)系,這就是依賴倒置原則的應(yīng)用.
使用這個原則需要遵循幾個規(guī)則:
-
每個類
應(yīng)該都具有接口或抽象類,或者同時具備抽象類和接口. - 變量的表面類型盡量是接口或者是抽象類
- 任何類都不應(yīng)該從具體類派生
- 盡量不應(yīng)該重寫基類的方法
- 結(jié)合里氏替換原則使用
依賴倒置原則是六中設(shè)計原則中最難以實現(xiàn)的原則,它是實現(xiàn)開閉原則的重要途徑.在項目中抓住"面向接口編程"的思想就基本抓住了依賴倒置的原則
接口隔離原則
這里先理解什么是接口.接口分為兩種:
- 實例接口:Person 張三=new Person(),在這里的張三就是Person的實例接口
- 類接口:在我們使用多線程的時候,大家肯定發(fā)現(xiàn)有一個接口叫做java.lang.Runnable這個就是一個類接口.
接口隔離原則的定義
- 客戶端不應(yīng)該依賴它不需要的接口.
- 類間的
依賴關(guān)系
應(yīng)該建立在最小的接口上.
接口相當于一個角色,我們不應(yīng)該將不同的角色都交給一個接口.同時不應(yīng)該強迫客戶依賴于他們不用的方法,這一點十分重要.
在我們?nèi)粘>幋a的過程中一個類,往往會有不同性質(zhì)的對象,比如一個汽車,可能有奔馳,寶馬,凱德拉克,特使拉等等,這些不同的車有一些不同的特性,對待這些不同的特性我們應(yīng)該對應(yīng)每一個不同的品牌寫不同的接口.
接口隔離原則的應(yīng)用
上面的應(yīng)用實踐可以看出一個接口只對一個子模塊或者業(yè)務(wù)邏輯進行服務(wù).這里還要提醒接口不是越小越好,接口太小則會導致接口數(shù)量劇增,給開發(fā)帶來難度;如果接口太大,靈活性降低,將無法提供定制服務(wù),給項目帶來無法預計的風險.
迪米特法則
迪米特法則的定義
國外的定義往往通常是以發(fā)現(xiàn)者的名字所取名的,這個法則又叫做最少只是原則,其意義是:一個對象應(yīng)當對其他對象盡可能的少的了解,其中對迪米特法則最具有代表性的幾種表述如下:
- 只同你直接的朋友們通信
- 不要跟陌生人說話
- 每一個軟件單位對其他的單位都只有最少的了解,這些了解僅局限于那些與本單位密切相關(guān)的軟件單位
其實意義就是兩個類之間的聯(lián)系是通過一個朋友類
相互關(guān)聯(lián),這樣可以減少類之間的關(guān)系,降低類之間的耦合,提高類的復用率.
迪米特法則的應(yīng)用
我通過call方法傳遞進我的Friend,然后同F(xiàn)riend中的變量Stranger,我可以間接訪問Stranger中方法,這樣Friend就是一個類似介質(zhì)的功能.
這里我對這個法則的感悟不是很深,暫時先記住,以后在后續(xù)的開發(fā)過程中可能可以找到這個法則的應(yīng)用場景,和一些優(yōu)點.
開閉原則
開閉原則的定義
一個軟件應(yīng)當對擴展開放,對修改關(guān)閉.
在設(shè)計一個模塊的時候,應(yīng)當使用這個模塊可以在不被修改的前提下被擴展.面向?qū)ο缶幊讨?開閉原則是最基本的原則,其他五大原則(單一職責,迪米特原則,里氏替換原則,依賴倒置原則,接口隔離原則)這些都是開閉原則的具體形態(tài),以及是開閉原則的手段和工具.開閉原則一般可以通過以下幾個方面體現(xiàn):
- 開閉原則提高復用性
- 開閉原則提高可維護性
- 開閉原則提高靈活性
- 開閉原則有利測試
開閉原則的應(yīng)用
上圖是一個書店商品正常情況下的類.因為商店的促銷需要來一個打折,所以在之前類通過繼承的方式解決了這個問題.
這個就是開閉原則的體現(xiàn)對擴展開放,對修改關(guān)閉,我沒有修改之前的代碼,同時實現(xiàn)了功能的擴展,這是面向?qū)ο缶幊讨兄陵P(guān)重要的.
開閉原則解決問題的關(guān)鍵在與抽象化
.把所有可能的行為抽象為抽象底層,這個抽象底層規(guī)定了所有的具體實現(xiàn)必須提供的方法的特征,給系統(tǒng)定義一個一勞永逸的抽象設(shè)計,設(shè)計允許有無窮盡的行為在實現(xiàn)層被實現(xiàn).
在抽象層一定要竟可能的預見所有可能的擴展,在任何擴展情況下的系統(tǒng)的抽象底層不需修改,從而滿足開閉原則的第二條(對修改關(guān)閉).通過從抽象層導出一個或多個新的具體類改變系統(tǒng)的行為,通過使用新的行為來擴展,從而滿足開閉原則的第一條(可以擴展).