物件導向設計原則

2022-05-15 15:59:02 字數 3761 閱讀 4807

目錄

一、開放封閉原則

概念理解

開放封閉原則是指在進行物件導向設計中,設計類或者程式應該遵循兩點:對擴充套件開放和對修改關閉。這樣,乙個模組在實現的過程中,就可以在不修改原來的模組(修改關閉)基礎上,擴充套件器功能(擴充套件開放)。

開閉原則的實現方法

為了滿足開閉原則的對修改關閉,對擴充套件開放原則,應該對軟體系統中的不變的部分加以抽象

實現原則:

優點:開閉原則的相對性

軟體系統的構建是乙個需要不斷重構的過程,在這個過程中,模組的功能抽象,模組與模組之間的關係,都不會從一開始就非常清晰明了。所以構建100%滿足開閉原則的軟體系統是非常困難的,這就是開閉原則的相對性。

但是在設計過程中,通過對模組功能的抽象(介面定義),模組之間的關係的抽象(通過介面呼叫),抽象與實現的分離(面向介面的程式設計)等,可以盡量接近滿足開閉原則。

二、裡式替換原則

所有引用父類的地方必須能夠透明地使用其子類的物件。

概念理解

只要父類能出現的地方子類就可以出現,而且替換為子類也不會產生任何錯誤或異常,使用者不需要知道是父類還是子類。但是,反過來就不行了,有子類出現的地方,父類未必就能適應。

滿足條件:

體現原則:

裡式替換原則為我們是否應該使用繼承提供了判斷的依據,不再是簡單地根據兩者之間是否有相同之處來決定是否使用繼承。

裡式替換原則的引申意義:子類可以擴充套件父類的功能,但是不能改變父類原有的功能。

表現幾點:

優點:

class

user:

defshow_name(self):

pass

classvipuser(user):

defshow_name(self):

pass

defshow_user(u):

res =u.show_name()

vipuser這個類繼承了user,它重寫了父類的show_name,這個時候就必須保證子類的show_name方法的引數和返回值。不然當使用show_user方法呼叫的時候會出現問題。

示例重構違反lcp的設計:

如果兩個具體的類a,b的關係違反了lsp的設計,(假設是從b到a的繼承關係),那麼根據具體的情況可以在下面的兩種重構方案中選擇一種:

在進行設計的時候,我們盡量從抽象類繼承,而不是從具體類繼承。

如果從繼承等級樹來看,所有葉子結點應該是具體類,而所有樹枝節點應該是抽象類或者介面。當然這只是乙個一般性的指導原則,使用的時候還要具體情況具體分析。

在很多情況下,在設計初期我們類之間的關係不是很明確,lsp則給了我們乙個判斷和設計類之間關係的基準:需不需要繼承,以及怎樣設計繼承關係。

三、依賴倒置原則

高層模組不應該依賴於底層模組,二者都應該依賴於抽象。

抽象不應該依賴於細節,細節應該依賴於抽象。

針對介面程式設計,不要針對實現程式設計。

概念理解

依賴:在程式設計中,如果乙個模組a呼叫了另乙個模組b,我們稱模組a依賴模組b。

高層模組和底層模組:在乙個應用程式中,我們有一些低層次的類,這些類實現了一些基本的或者初級的操作,我們稱之為底層模組,另外有一些高層次的類,這些類封裝了某些複雜的邏輯,並且依賴於低層次的類,這些類我們稱之為高層模組。

依賴倒置:物件導向程式設計相對於面向過程程式設計而言,依賴關係被倒置了。因為傳統的結構化程式設計中,高層模組總是依賴於底層模組。

問題提出:

robert c. martin在書中給出了bad design的幾個特徵:

這其中導致bad design的乙個很大的原因是高層模組過分依賴底層模組。

但是乙個良好的設計應該是系統的每個部分都是可替換的。如果高層模組過分依賴底層模組,一方面一旦底層模組需要替換或者修改,高層模組將受到影響,另外一方面,高層模組很難可以重用。

問題的解決:

robert c. martin提出了dependency inversion principle (dip) 原則。

dip給出了乙個解決方案:在高層模組與底層模組之間,引入乙個抽象介面層。

high level classes(高層模組) --> abstraction layer(抽象介面層) --> low level classes(低層模組)。

抽象介面是對底層模組的抽象,低層模組繼承或者實現該抽象介面。

這樣高層模組不直接依賴低層模組,而是依賴抽象介面層。抽象介面也不依賴低層模組的實現細節,而是低層模組依賴(繼承或實現)抽象介面。

類與類之間都是通過抽象介面層來建立關係的。

怎麼使用依賴倒置原則

1、依賴於抽象

2、設計介面而非設計實現

例外:有些類不可能變化,在可以直接使用具體類的情況下,不需要插入抽象層,如字串。

3、避免傳遞依賴

優點:四、介面隔離原則

不能強迫使用者依賴那些它們不適用的介面。

概念理解

換句話說,使用多個專門的介面比使用單一的總介面要好。

介面隔離原則指導我們:

下面我們舉例說明怎麼設計介面或類之間的關係,使其不違反isp原則。

假如有乙個door,有lock,unlock功能,另外,可以在door上安裝乙個alarm而使其具有報警功能。使用者可以選擇一般的door,也可以選擇具有報警功能的door。

isp原則的違反例一:在door介面裡定義所有的方法。

但這樣一來,依賴door介面的commondoor卻不得不實現未使用的alarm()方法。違反了isp原則。

isp原則的違反例二:在alarm介面定義alarm方法,在door介面定義lock,unlock方法,door介面繼承alarm介面。

跟方法一一樣,依賴door介面的commondoor卻不得不實現未使用的alarm()方法。違反了isp原則。

遵循isp原則的例一:通過多重繼承實現

在alarm介面定義alarm方法,在door介面定義lock,unlock方法。介面之間無繼承關係。commondoor實現door介面,alarmdoor有2種實現方案:

1)同時實現door和alarm介面。

2)繼承commondoor,並實現alarm介面。

第2)種方案更具有實用性。

這樣的設計遵循了isp設計原則。

遵循isp原則的例二:通過關聯(或者叫做組合)實現

在這種方法裡,alarmdoor實現了alarm介面,同時把功能lock和unlock委讓給commondoor物件完成。

這種設計遵循了isp設計原則。

介面分隔原則的優點和適度原則

五、單一職責原則

如果乙個類需要改變,改變它的理由永遠只有乙個。如果存在多個改變它的理由,就需要重新設計該類。也就乙個類只做一件事。

只能讓乙個類/介面/方法有且僅有乙個職責。

如果乙個類具有乙個以上的職責,那麼就會有多個不同的原因引起該類變化,而這種變化將影響到該類不同職責的使用者(不同使用者):

這違反了設計的開閉原則,也不是我們所期望的。

物件導向設計原則

oo原則 封裝變化 多用組合,少用繼承 針對介面程式設計,不針對實現程式設計 為互動物件之間的松耦合而努力 類應該對擴充套件開放,對修改關閉 依賴抽象,不要依賴具體類 只和朋友交談 別找我,我會找你 類應該只有乙個改變的理由 從設計原則到設計模式 針對介面程式設計,而不是針對實現程式設計 客戶無需知...

物件導向設計原則

物件設計原則 物件導向設計原則 物件導向設計的基石是 開 閉 原則。開一閉 原則講的是 乙個軟體實體應當對擴充套件開放,對修改關閉。這個規則說的是,在設計乙個模組的時候,應當使這個模組可以在不被修改的前提下被擴充套件。從另外乙個角度講,就是所謂的 對可變性封裝原則 對可變性封裝原則 意味著兩點 1 ...

物件導向設計原則

oo原則 封裝變化 多用組合,少用繼承 針對介面程式設計,不針對實現程式設計 為互動物件之間的松耦合而努力 類應該對擴充套件開放,對修改關閉 依賴抽象,不要依賴具體類 只和朋友交談 別找我,我會找你 類應該只有乙個改變的理由 從設計原則到設計模式 針對介面程式設計,而不是針對實現程式設計 客戶無需知...