1. 程式人生 > >程式碼設計的幾個基本原則

程式碼設計的幾個基本原則

1、OCP(Open-Close Principle)開閉原則

Software entities should be open for extension,but closed for modification,(在設計一個模組的時候,應當使這個模組可以在不被修改的前提下擴充套件)。

對擴充套件開放open,對修改關閉close。

如何實現?1,抽象化是關鍵,2對可變性的封裝原則(Principle of Encapsulation of Variation EVP)。3.對可能的拓展預留介面

備註:

1) 對於抽象化, 我的理解是, 介面是相對穩定的, 實現是根據需求多變的。對於大多數可能預料的變化點, 我們可以抽取出共性或者常態點, 進行介面的封裝, 而選擇不同的實現類嵌入模組, 從而達到可擴充套件的作用。

2) 對於某個業務點, 可能以後有多種介入處理的情況, 那麼這時候可以將業務抽象成事件(event)介面和監聽器(listener)介面, 不同的處理需求生成不同的listener, 接入模組的listener收集器, 從而得到業務點的介入機會。最後達到功能的擴充套件。

典型容易理解的例子,工廠模式。當需要新增加一個類的時候,直接繼承product介面就可以了 , 由工廠類來組裝產生需要的product, 而不用大範圍修改原有程式碼。OCP~

2、Liskov Subsitution Principle(LSP)里氏代換原則

就是子類可以代替父類出現的任何地方,在抽象的時候,重要的要理解的一個地方兩個類之間是什麼關係,是“has-A”?還是“Is-a”的關係。在 “has-a”的關係中,兩個類存在的是依賴的關係(在類A裡面存在類B的的變數);在“Is-a”的關係中,可以提取這兩個類的“共同程式碼”放在抽象類 C中,然後A,B繼承與C,這也是一種重構。

3、Dependency Inversion Principle(DIP)依賴倒轉原則

就是在我們程式設計的時候方法的引數型別,變數,對於其他具體類的依賴,我們儘量的使用抽象類。

就是說盡量依賴於抽象,而不是依賴於實現。

在書中兩種表述:

(1)Abstraction should not depend on details.details should depend on abstraction。(抽象不應當依賴於細節,細節應當依賴於抽象)。

Abstraction就像是建築物的基礎,而其實現類就是在基礎上面一層一層的往上面走。你拆掉最上面 那層,和拿走最下面的基礎,有什麼不同了,這就是差異了。所以Abstraction是要相當的穩定,是維護的重點。也正是因為穩定,所以我們儘量的依賴 於Abstraction,既是穩定系統,也是靈活系統。

(2)Program to an Interface,not an implementation(要針對介面程式設計,不要針對實現程式設計)

應當使用java介面和抽象java類進行變數的型別宣告,引數的型別宣告,方法返回值的型別和資料型別的轉換。

備註:

依賴倒轉原則的作用在於多模組或者類間有統一的”知識”, 都知道有這個介面, 都知道這個介面是這樣用,會返回什麼資料。

至於最初的實現類是什麼, 只有提供該介面功能的實現類自己關心, 其他模組或者類只管用就行了。即使以後需求更改, 實現會換成別的一個, 其他模組和類也無需修改程式碼。

例如A模組提供了一個介面是: List getProducts()

而B和C會使用該模組, 他們只知道這個方法就會返回List , 他們知道List和Product代表什麼.

但他們不會管你的介面內部是使用List list = new ArrayList() , 還是List lis = new LinkedList()

或者具體的Product是什麼(可能是衣服,鞋子等)

4、Interface Segregation Principle(ISP)介面隔離原則

限制一個實體對另一個實體通訊時候的寬度。

就是一個類對另外一個類依賴的時候,應當是建立在最小的介面上面。對於介面隔離原則來說,有兩種介面,一種是真正意義上面的“java 介面”Interface;另外一種是指一個類的方法的集合。對於這來兩種有,兩個介面隔離的原則,對於一個類裡面的方法的集合的介面隔離,我們稱作是 “角色隔離原則”;另外一種叫做“定製服務”。

定製服務,就是一個類,我給你這個客戶端一些方法,我放在一個java介面(Interface)裡面。給另外一個客戶端另外一些方法,放在另外一個介面(Interface)。

角色隔離原則,是指客戶端要多個不同的類的方法,我們就搞幾個不同類別的介面(Interface),在書中,這麼比喻的,就相當於電影劇本里面的人物,我們找人來演,這個人就是具體的類。這就叫做角色隔離原則。

5、Composition/Aggregation Reuse Principle(CARP)組合/聚合複用原則

就是說要儘量的使用合成和聚合,而不是繼承關係達到複用的目的。

其實這裡最終要的地方就是區分“has-a”和“is-a”的區別。相對於合成和聚合,繼承的缺點在於:父類的方法全部暴露給子類。父類如果發生變化,子類也得發生變化。聚合的複用的時候就對另外的類依賴的比較的少。

6、Least Knowledge Principle(LKP)最少知識原則,又稱為“Law of Demeter”迪米特原則

和ISP介面隔離原則一樣,限制類與類之間的通訊。ISP限制的是寬度,而LoD迪米特原則限制的是通訊的廣度和深度。

LoD在廣度上面,儘量減少遠距離類的關聯,而使用與自己有關的類,並且也與遠距離類有關的類。

可是這種做法有一點麻煩。多個遠距離類產生關聯的時候,不怎麼容易處理,所以增加一個遠距離類的抽象類。所有的遠距離類都是通過抽象類的形式來訪問。

在深度上面,控制權限是最重要的,對於類,一個是default 和public,儘量最小許可權;對於成員,private,default,protected,public。往上面走,許可權越小,依賴的耦合就越小。

有幾種描述:

(a)Only talk to your immediate friends.

(b)Don’t talk to strangers.

設計模式“facade”,”調停者模式”。在這裡是IoD的典型表現。

備註:

當一個系統比較大的時候, 如果所有的模組都自己去尋找與自己相關的類的時候, 那麼引用關係就會變得極度複雜, 耦合度高。

這個時候最好就設定一個為各個模組所熟悉的物件, 例如Context容器。

另外,各個模組可以應用facade模式, 提供一個簡單的對外介面, 並將其嵌入Context容器。

這樣, 模組間通過熟人Context來獲取其他模組的Facade介面, 即符合依賴倒轉原則, 介面隔離原則和迪米特原則。