很久以前就知道物件導向設計有一些公認的基本原則,可都是零零碎碎的了解一部分,雖然在實踐的過程中也有意識的用到了一些,可是從來沒有系統的總結過,這是我從網上找到的比較詳細的介紹,就當是讀書筆記吧
所有的設計模式都是對不同的可變性的封裝,從而使系統在不同角度達到「開閉原則」的要求。
在軟體軟體系統中,乙個模組設計得好不 好的最主要、最重要的標誌,就是該模組在多大程度上將自己的內部資料和其他與實現有關的細節隱藏起來。乙個設計得好的模組可以將它所有的實現細節隱藏起 來,徹底地將提供給外界的api和自己的實現分隔開來。這樣一來,模組與模組之間就可以僅僅通過彼此的api相互通訊,而不理會模組內部的工作細節。
oo設計根本的指導原則是提高可維護性和可復用性。這些原則主要有:
1. 開閉原則
乙個軟體實體應該對擴充套件開放,對修改關閉。
在設計乙個模組的時候,就當使這個模組可以在不被修改的前提下被擴充套件。換言之,就當可以在不必修改源**的情況下改變這個模組的行為。
如何做到既不修改,又可以擴充套件?
解決問題的關鍵在於抽象化:在c#語言裡,可以給出乙個或多個抽象c#類或c#介面,規定出所有的具體類必須提供的方法特徵作為系統設計的抽象層。這個抽象層預見了所有的可能擴充套件,因此,在任何擴充套件情況下都不會改變。這就使得系統的抽象層不需要修改,從而滿足了—對修改關閉。
同時,由於從抽象層匯出乙個或多個新的具體類可以改變系統的行為,因此系統的設計對擴充套件是開放的。
開閉原則實際上是對「對可變性的封閉原則「:找到乙個系統的可變因素,將之封裝起來。這個原則意昧著兩點:
1) 乙個可變性不應當散落在**的很多角落裡,而應當被封裝到乙個物件裡面。同一種可變性的不同表象意昧著同乙個繼承等級結構中的具體子類。
繼承就當被看作是封裝變化的方法,而不應當被認為是從一般的物件生成特殊物件的方法。
2) 一種可變性不應當與另一種可變性混合在一起。(所有類圖的繼承結構一般不會超過兩層,不然就意昧著將兩種不同的可變性混合在了一起。)
開閉原則是總的原則,其它幾條是開閉原則的手段和工具。
2. 依賴倒轉原則
依賴倒轉原則講的是:要依賴於抽象,不要信賴於實現。
開閉原則是目標,而達到這一目標的手段是依賴倒轉原則。
抽象層次包含的是應用系統的商務邏輯和巨集觀的、對整個系統來說重要的戰略性決定,是必然性的體現;而具體層次則含有一些次要的與實現有關的演算法和邏輯,以及戰術性的決定,帶有相當大的偶然性選擇。具體層次的**是會經常有變動的,不能避免出現錯誤。
抽象層次含有乙個應用系統最重要的巨集觀商務邏輯,是做戰略判斷和決定的地方,那麼抽象層次就應當是較為穩定的,應當是復用的重點;也應當是維護的重點。
在很多情況下,乙個c#程式需要引用乙個物件。這個時候,如果這個物件有乙個抽象型別的話,應當使用這個抽象型別作為變數的靜態型別。這就是針對介面程式設計的含義。
工廠模式將建立乙個類的例項的過程封裝起來,消費這個例項的客戶端僅僅取得例項化的結果,以及這個例項的抽象型別。 當然,任何方法都無法迴避c#語言所要求的new關鍵字和直接呼叫具體類的構造子的做法(這違背了黎克特制代換原則)。簡單工廠模式將這個違反「開閉原 則」和依賴倒轉原則的做法封裝到了乙個類裡面,而工廠方法模式將這個違反原則的做法推遲到了具體工廠角色中。通過適當的封裝,工廠模式可以淨化大部分的結 構,而將違反原則的做法孤立到易於控制的地方。
聯合使用c#介面和c#抽象類:宣告型別的工作由c#介面承擔,但是 同時給出的還有乙個c#抽象類,為這個介面給出乙個預設實現。如果乙個具體類直接實現這個c#介面的話,它就必須自行實現所有的介面;相反,如果 它繼承自抽象類的話,它就可以省去一些不必要的方法,因為它可以從抽象類中自動得到這些方法的預設實現。這其實就是預設適配模式。
依賴倒轉的缺點:
1) 因為依賴倒轉的緣故,物件的建立很可能要使用物件工廠,以避免對具體類的直接引用,此原則的使用還會導致大量的類。對不熟悉物件導向技術的工程師來說,維護這樣的系統需要較好地物件導向的設計知識。
2) 依賴倒轉原則假定所有的具體類都是會變化的,這也不總是正確的。有一些具體類可能相當穩定、不會發生變化,消費這個具體類例項的客戶端完全可以依賴這個具體型別,而不必為此發明乙個抽象型別。
3. 黎克特制代換原則
任何基類可以出現的地方,子類一定可以出現。
開閉原則的關鍵步驟是抽象化。而基類與子類的繼承關係就是抽象化的具體體現,黎克特制代換原則是對實現抽象化的具體步驟的規範。
4. 合成/聚合復用原則
要盡量使用合成/聚合,而不是繼承關係達到復用的目的。
合成/聚合原則要求我們首先考慮合成/聚合關係,黎克特制代換原則要求在使用繼承時,必須確定這個繼承關係符合一定的條件(繼承是用來封裝變化的;任何基類可以出現的地方,子類一定可以出現。)
合成/聚合原則就是在乙個新的物件裡面使用一些已有的物件,使之成為新物件的一部分;新的物件通過向這些物件的委派達到得復用已有功能的目的。
5. 迪公尺特原則
乙個軟體實體應當盡可能少的其他實體發生相互作用。模組之間的互動要少。這樣做的結果是當系統的功能需要擴充套件時,會相對更容易地做到對修改的關閉。
乙個物件應當對其他物件有盡可能少的了解。
迪公尺特原則的具體操作:
1) 優先考慮將乙個類設定成不變類。不變類易於設計、實現和使用。比如c# api中的string等類。
乙個物件與外界的通訊大體上分成兩種,一種是改變這個物件的狀態,另一種是不改變這個物件的狀態的。如果乙個物件的內部狀態根本就是不可能改變的,那麼它與外界的通訊當然就大大地減少。
當涉及任何乙個類的時候,都首先考慮這個類的狀態是否需要改變。即便乙個類必須是可變類,在給它的屬性設定賦值方法的時候,也要保持吝嗇的態度。除非真的需要,否則不要為乙個屬性設定賦值方法。
2) 盡量降低乙個類的訪問許可權。
3) 謹慎使用serializable,一旦將乙個類設定成serializable,就不能再在新版本中修改這個類的內部結構,包括private的方法和句段。
4) 盡量降低成員的訪問許可權。
6. 介面隔離原則
應當為客戶端提供盡可能小的單獨介面,而不要提供大的總介面。也即是使用多個專門的介面比使用單一的總介面要好。
介面隔離原則與迪公尺特都是對乙個軟體實體與其他的軟體實體的通訊限制。迪公尺特原則要求盡可能地限制通訊的寬度和深度,接品隔離原則要求通訊的寬度盡可能地窄。這樣做的結果使乙個軟體系統在功能擴充套件過程當中,不會將修改的壓力傳遞到其他物件。
乙個介面相當於劇本中的一種角色,而此角色在乙個舞台上由哪乙個演員來演則相當於介面的實現。因此,乙個介面應當簡單地代表乙個角色,而不是多個角色。如果系統涉及到多個角色的話,那麼每乙個角色都應當由乙個特定的介面代表。
定**務:如果客戶端僅僅需要某一些方法的話,那麼就應當向客戶端提供這些需要的方法,而不要提供不需要的方法。(向客戶端提供public介面是一種承諾,沒有必要做出不必要的承諾,過多的承諾會給系統的維護造成不必要的負擔。)
物件導向程式設計原則
宣告 下面列出的物件導向程式設計原則並非我個人總結,而是最近學習設計模式的筆記。目前只是列出剛看過的幾條,以後學到再繼續新增。1.單一職責原則 srp 單一職責原則,就是,就乙個類而言,應該僅有乙個引起它變化的原因。也就是說,乙個類應該只實現乙個單一的功能。為什麼呢?因為,如果乙個類承擔的職責過多,...
物件導向程式設計的原則
1.開閉原則 the open closed principle ocp 乙個模組在擴充套件性方面應該是開放的而在更改性方面應該是封閉的。因此在進行物件導向設計時要盡量考慮介面封裝機制 抽象機制和多型技術。該原則同樣適合於非物件導向設計的方法,是軟體工程設計方法的重要原則之一。我們以收音機的例子為例...
物件導向程式設計原則總結
單一職責原則 就乙個類而言 應該僅有乙個引起它變化的原因 如果乙個類承擔的職責過多 就等於把這些職責耦合在一起 乙個職責的變化可能會削弱或者抑制這個類完成其他職責的能力 這種耦合會導致脆弱的設計 當變化發生時 設計會遭受到意想不到的破壞 軟體設計真正要做的許多內容 就是發現職責並把那些職責相互分離 ...