1. 程式人生 > >《設計模式之禪》之六大設計原則下篇

《設計模式之禪》之六大設計原則下篇

本文主要講迪米特法則和開閉原則。

一、迪米特法則

1.定義

迪米特法則也稱最少知道原則,雖然名字不同,但描述的是同一個規則:一個物件應該對其他物件有最少的瞭解。通俗地講,一個類應該對自己需要耦合或呼叫的類知道得最少,你(被耦合或呼叫的類)的內部是如何複雜都和我沒關係,那是你的事情,我就知道你提供的這麼多public方法,我就呼叫這麼多,其他的我一概不關心。

2.迪米特法則對類的低耦合提出明確的要求

4層含義如下:

(1)只和朋友交流

迪米特法則還有一個解釋是:只與直接的朋友通訊。

什麼叫直接的朋友?
每個物件都必然會與其他物件有耦合關係,兩個物件之間的耦合就成為朋友關係,這種關係的型別有很多,例如組合、聚合、依賴等。

注意:
一個類只和朋友交流,不與陌生類交流,不要出現getA().getB().getC().getD()這種情況(在一種極端的情況下允許出現這種訪問,即每個點號後面的返回型別都相同),類與類之間的關係是建立在類間的,而不是方法間,因此一個方法儘量不引入一個類中不存在的物件,當然,JDK API提供的類例外。

(2)朋友間也是有距離的

人和人之間是有距離的,太遠關係逐漸疏離,最終形同陌路;太近就相互刺傷。對朋友關係描述最貼切的故事就是:兩隻刺蝟取暖,太遠取不到溫暖,太近刺傷對方,必須保持一個既能取暖又不刺傷對方的距離。迪米特法則就是對這個距離進行描述,即使是朋友類之間也不能無話不說,無所不知。

注意:迪米特法則要求類”羞澀”一點,儘量不要對外公佈太多public方法和非靜態的public變數,儘量內斂,多使用private、package-private、protected等訪問許可權。

(3)是自己的就是自己的

在實際應用中經常會出現這樣一個方法:放在本類中也可以,放在其他類中也沒有錯,那怎麼去衡量呢?你可以堅持這樣一個原則:如果一個方法放在本類中,既不增加類間關係,也對本類不產生負面影響,那就放置在本類中。

(4)謹慎使用Serializable

3.最佳實踐

迪米特法則的核心觀念:
類間解耦,弱耦合,只有弱耦合了以後,類的複用率才可以提高。其要求的結果就是:產生了大量的中轉或跳轉類,導致系統的複雜性提高,同時也為維護帶來了難度。所以我們在採用迪米特法則時,需要反覆權衡,既做到讓結構清晰,又做到高內聚低耦合。

二、開閉原則

1.定義

一個軟體實體如類、模組和函式應該對擴充套件開放,對修改關閉。

注意:
開閉原則對擴充套件開放,對修改關閉,並不意味著不做任何修改,低層模組的變更,必然要有高層模組進行耦合,否則就是一個孤立無意義的程式碼片段。

變化可以歸納為如下三類:

(1)邏輯變化

只變化一個邏輯,而不涉及其他模組,比如原有的一個演算法是ab+c,現在需要修改為ab*c,可以通過修改原有類中的方法的方式來完成,前提條件是所有依賴或關聯類都按照相同的邏輯處理。

(2)子模組變化

一個模組變化,會對其他的模組產生影響,特別是一個低層次的模組變化必然引起高層模組的變化,因此在通過擴充套件完成變化時,高層次的模組修改是必然的。

(3)可見檢視變化

可見檢視是提供給客戶使用的介面,如JSP程式、Swing介面等,該部分的變化一般會引起連鎖反應(這個連鎖反應,我相信使用過JSP作為檢視層的朋友們都深有感觸)

2.為什麼要採用開閉原則

都說開閉原則是非常重要的,可通過以下幾個方面來理解其重要性:

(1)開閉原則對測試的影響

(2)開閉原則可以提高複用性

(3)開閉原則可以提高可維護性

(4)面向物件開發的要求

3.如何使用開閉原則

(1)抽象約束

抽象是對一組事物的通用描述,沒有具體的實現,也就表示它可以由非常多的可能性,可以跟隨需求的變化而變化。因此,通過介面或抽象類可以約束一組可能變化的行為,並且能夠實現對擴充套件開放,其包含三層含義:
第一,通過介面或抽象類約束擴充套件,對擴充套件進行邊界限定,不允許出現在介面或抽象類中不存在的public方法;
第二,引數型別、引用物件儘量使用介面或抽象類,而不是實現類;
第三,抽象層儘量保持穩定,一旦確定即不允許修改;

(2)元資料控制模組行為

儘量使用元資料來控制程式的行為,減少重複開放。

什麼是元資料?
用來描述環境和資料的資料,通俗地說就是配置引數,引數可以從檔案中獲得,也可以從資料庫中獲得。

(3)指定專案章程

在一個團隊中,建立專案章程是非常重要的,因為章程中指定了所有人員都必須遵守的約定,對專案來說,約定優於配置。

(4)封裝變化

對變化的封裝包含兩層含義:
第一,將相同的變化封裝到一個介面或抽象類中;
第二,將不同的變化封裝到不同的介面或抽象類中,不應該由兩個不同的變化出現在同一個介面或抽象類中;

封裝變化,也就是受保護的變化,找出預計有變化或不穩定的點,我們為這些變化點建立穩定的介面,準確地講是封裝可能發生的變化,一旦預測或”第六感”發覺有變化,就可以進行封裝,23種設計模式都是從各個不同的角度對變化進行封裝的。

4.最佳實踐

我們在使用開閉原則時要注意以下幾個問題?

    • 開閉原則也只是一個原則(開閉原則只是精神口號,實現擁抱變化的方法非常多,並不侷限於6大設計原則,但是遵循這6大設計原則基本上可以應對大多數變化);
    • 專案規章非常重要(優秀的章程可以給專案帶來很多好處,如提高開放效率、降低缺陷率、提高團隊士氣、提高技術成員水平等);
    • 預知變化(適應未來的變化,比如未來新增某項功能需求,在不影響現有的架構下,輕鬆擴充套件就能實現等);