1. 程式人生 > >java--面向物件七大設計原則

java--面向物件七大設計原則


1、 每一種設計思想的精準含義,具體如下:
先從整體認識這七種設計思想。
一、開閉原則:
這一條放在第一位來理解,它的含義是對擴充套件開放,對修改關閉。解釋一下就是,我們寫完的程式碼,不能因為需求變化就修改。我們可以通過新增程式碼的方式來解決變化的需求。
當然,這是一種理想的狀態,在現實中,我們要儘量的縮小這種修改。
再解釋一下這條原則的意義所在,我們採用逆向思維方式來想。如果每次需求變動都去修改原有的程式碼,那原有的程式碼就存在被修改錯誤的風險,當然這其中存在有意和無意的修改,都會導致原有正常執行的功能失效的風險,這樣很有可能會展開可怕的蝴蝶效應,使維護工作劇增。
說到底,開閉原則除了表面上的可擴充套件性強以外,在企業中更看重的是維護成本。
所以,開閉原則是設計模式的第一大原則,它的潛臺詞是:控制需求變動風險,縮小維護成本。
以下幾種原則,都是為此原則服務的。
二、里氏替換選擇:
此原則的含義是子類可以在任何地方替換它的父類。解釋一下,這是多型的前提,我們後面很多所謂的靈活,都是不改變宣告型別的情況下,改變例項化類來完成的需求變更。當然,繼承的特性看似天然就滿足這個條件。但這裡更注重的是繼承的應用問題,我們必須保證我們的子類和父類劃分是精準的。
里氏替換原則的潛臺詞是:儘量使用精準的抽象類或者介面。
三、單一職責原則:
單一職責的含義是:類的職責單一,引起類變化的原因單一。解釋一下,這也是靈活的前提,如果我們把類拆分成最小的職能單位,那組合與複用就簡單的多了,如果一個類做的事情太多,在組合的時候,必然會產生不必要的方法出現,這實際上是一種汙染。
舉個例子,我們在繪製圖案的時候,用“點”組成圖和用“直線”組成圖,哪個更靈活呢?一定是“點”,它可以繪製任何圖形,而直線只能繪製帶有直線條的圖案,它起碼無法畫圓。
單一職責的潛臺詞是:拆分到最小單位,解決複用和組合問題。
四、介面隔離原則:
介面隔離原則可以說是單一職責的必要手段,它的含義是儘量使用職能單一的介面,而不使用職能複雜、全面的介面。很好理解,介面是為了讓子類實現的,如果子類想達到職能單一,那麼介面也必須滿足職能單一。
相反,如果介面融合了多個不相關的方法,那它的子類就被迫要實現所有方法,儘管有些方法是根本用不到的。這就是介面汙染。
介面隔離原則的潛臺詞是:拆分,從介面開始。
五、依賴倒置原則:
想要理解依賴倒置原則,必須先理解傳統的解決方案。面相物件的初期的程式,被呼叫者依賴於呼叫者。也就是呼叫者決定被呼叫者有什麼方法,有什麼樣的實現方式,這種結構在需求變更的時候,會付出很大的代價,甚至推翻重寫。
依賴倒置原則就是要求呼叫者和被呼叫者都依賴抽象,這樣兩者沒有直接的關聯和接觸,在變動的時候,一方的變動不會影響另一方的變動。
其實,依賴倒置和前面的原則是相輔相成的,都強調了抽象的重要性。
依賴倒置的潛臺詞是:面向抽象程式設計,解耦呼叫和被呼叫者。
六、迪米特原則:
迪米特原則要求儘量的封裝,儘量的獨立,儘量的使用低級別的訪問修飾符。這是封裝特性的典型體現。
一個類如果暴露太多私用的方法和欄位,會讓呼叫者很茫然。並且會給類造成不必要的判斷程式碼。所以,我們使用盡量低的訪問修飾符,讓外界不知道我們的內部。這也是面向物件的基本思路。這是迪米特原則的一個特性,無法瞭解類更多的私有資訊。
另外,迪米特原則要求類之間的直接聯絡儘量的少,兩個類的訪問,通過第三個中介類來實現。
迪米特原則的潛臺詞是:不和陌生人說話,有事去中介。
七、組合/聚合複用原則:
此原則的含義是,如果只是達到程式碼複用的目的,儘量使用組合與聚合,而不是繼承。這裡需要解釋一下,組合聚合只是引用其他的類的方法,而不會受引用的類的繼承而改變血統。
繼承的耦合性更大,比如一個父類後來新增實現一個介面或者去掉一個介面,那子類可能會遭到毀滅性的編譯錯誤,但如果只是組合聚合,只是引用類的方法,就不會有這種巨大的風險,同時也實現了複用。
組合聚合複用原則的潛臺詞是:我只是用你的方法,我們不一定是同類。

2、 在學習面向物件七大設計原則時需要注意以下幾點:
a) 高內聚、低耦合和單一職能的“衝突”
實際上,這兩者是一回事。內聚,要求一個類把所有相關的方法放在一起,初看是職能多,但有個“高”,就是要求把聯絡非常緊密的功能放在一起,也就是說,從整體看,是一個職能的才能放在一起,所以,兩者是不同的表述而已。
這裡很多人理解成複合類,但複合類不是高內聚,而是雜亂的放在一起,是一種設計失誤而已。
b) 多個單一職能介面的靈活性和宣告型別問題
如果一個類實現多個介面,那麼這個類應該用哪個介面型別宣告呢?應該是用一個抽象類來繼承多個介面,而實現類來繼承這個介面。宣告的時候,型別是抽象類。
c) 最少知識原則和中介類氾濫兩種極端情況
這是另一種設計的失誤。迪米特原則要求類之間要用中介來通訊,但類多了以後,會造成中介類氾濫的情況,這種情況,我們可以考慮中介模式,用一個總的中介類來實現。
當然,設計模式都有自己的缺陷,迪米特原則也不是十全十美,互動類非常繁多的情況下,要適當的犧牲設計原則。
d) 繼承和組合聚合複用原則的“衝突”
繼承也能實現複用,那這個原則是不是要拋棄繼承了?不是的。
繼承更注重的是“血統”,也就是什麼型別的。而組合聚合更注重的是借用“技能”。並且,組合聚合中,兩個類是部分與整體的關係,組合聚合可以由多個類的技能組成。在C#和Java中只有單繼承。
這個原則不是告訴我們不用繼承了,都用組合聚合,而是在“複用”這個點上,我們優先使用組合聚合。

面向物件設計原則的共性問題:
1、這麼多設計模式,都要學習和使用麼?
答:我們只是掌握總體的原則,然後學習常用的就行了。實際開發中也不是每種設計模式都會經常用到。因為歸根結底,設計模式也好,架構也好,都是為需求服務的,沒有需求業務模型,不能生搬硬套模式。我們在學習的時候,多學一些總是好的,但只是為了開闊自己的眼界。
2、設計模式是規範麼?是不是好的程式必須用設計模式?
答:嚴格來說,好的程式遵循的是設計原則,而非設計模式。現在就出現很多新的演變出來的模式,這些都是因為出現了新業務的原因,設計模式不是規範,只是一種借鑑。
3、使用設計模式會不會增加開發難度?
答:開發階段會的,而且會延長開發時間。但一個專案或產品從開始到結束,開發只是其中很小的一部分,考慮到維護和擴充套件成本,才會出現設計模式。從整體考慮,設計模式是減少了開發時間和成本的。