大家一起学面向对象设计模式系列Chapter 02 软件设计的基本原则
?????我們為什么要使用設計模式呢?有人可能會說為了設計出"高內聚低耦合"的軟件。"高內聚低耦合"的軟件實際上也就是本文所說的具有可維護性和可復用性的軟件。
?????這篇文章主要講解兩方面內容,這兩方面是軟件設計中很重要,也是很關鍵的內容,希望大家認真思考并深刻理解。第一部分就是關于軟件的可維護性和可復用性的相關內容,第二部分就是在第一部分的基礎上逐條講解面向對象軟件設計的基本原則,本文內容都是些很理論性的東西,這些理論是軟件設計的基礎。凡是有理論的地方,就有如何恰當的將理論應用到實踐中去的問題,設計模式是對于學習OO設計原則的具體指導,也就是說設計模式就是將這些理論應用到實踐的一種成熟的方式。
?????軟件的可維護性和可復用性
?????首先來上一段大師所說的話,很經典。
“通常認為,一個易于維護的系統,就是復用率較高的系統;而一個復用率較高的系統,就是一個易于維護的系統。但是實際上,可維護性和可復用性是兩個獨立的目標,就像兩只奔跑的兔子一樣,并不總是方向一致的。對于面向對象的軟件系統設計來說,在支持可維護性(Maintainability)的同時,提高系統的可復用性(Reuseability)是一個核心的問題。”--《Java與模式》閻宏博士
????? 軟件系統的可維護性:
?????軟件維護就是軟件的再生。一個好的軟件設計,必須能夠允許新的設計要求以比較容易和平穩的方式加入到已有的系統中去,從而使這個系統能夠不斷的的煥發出活力。一個可維護性較好的系統,應當允許維護工作能夠以容易、準確、安全和經濟的形式進行。
【導致可維護性較低的原因】
1、過于僵硬:在系統中加入一個新的功能,不管大小都很難,不僅意味著建造一個獨立的新的模塊,而且因為這個新功能會波及很多其他模塊,最后成跨越幾個模塊的改動。
2、過于脆弱:與軟件的過于僵硬同時存在,是軟件系統在修改已有代碼時過于脆弱。對一個地方的修改,往往會導致看上去沒有什么關系的另外一個地方發生故障。
3、復用率低:所謂復用,就是指一個軟件的組成部分,可以在同一個項目的不同地方甚至另一個項目中重復使用。復用率低,指當一段代碼,函數,模塊的功能可以在新的模塊或新的系統使用,但是已有代碼依賴于其他很多東西,很難分開。
4、黏度過高:一個改動可以保存原始設計意圖和原始設計框架的方式進行,也可以以破壞原始意圖和框架進行。第一種方法對系統的未來有利,第二種辦法是權宜之計,可以解決短期的問題,但是會犧牲中長期的利益。如果一個系統中使用第二種方法比使用第一種方法容易,那么就是黏度過高。
【設計的目標】
1、可擴展性:新的性能可以很容易地加入到系統中去,就是可擴展性。這就是系統“過于僵硬”的屬性的方面。
2、靈活性:可以允許代碼修改平穩地發生,而不會波及到很多其他的模塊,這就是靈活性。靈活性其實就是“過于脆弱”的屬性的方面。
3、可插入性:可以很容易地將一個類抽出去,同時將另外一個有同樣接口的類加入進來,這就是可插入性。其實,這就是“黏度過高”的方面。
????? 軟件系統的可復用性:
【軟件復用的好處】
1、較高的生產效率;
2、較高的軟件質量;
3、恰當使用復用可以改善系統的可維護性。
【傳統的復用形式】
1、代碼的剪貼復用;
2、算法的復用;
3、數據結構的復用。
【面向對象設計的復用】
在面向對象語言中,數據的抽象化,繼承,封裝和多態性使得一個系統可以在更高層次上提供可復用性。數據的抽象化和繼承關系使得概念和定義可以復用;多態性使得實現和應用得到復用;而抽象化和封裝可以保持和促進系統的可維護性,復用的重點轉移到含有宏觀商業邏輯的抽象層次上。在面向對象的設計里面,可維護性復用是以設計原則和設計模式為基礎的。
?????提高系統可維護性和可復用性的設計原則
1、“開-閉”原則(Open-Closed Principle,或者OCP);
一個軟件實體應該對擴展開放,對修改關閉;
在設計一個模塊的時候,應當使這個模塊可以在不被修改的前提下被擴展。換言之,應當可以在不必修改源代碼的情況下改變這個模塊的行為。這個原則實際上是對“對可變性的封閉原則“:找到一個系統的可變因素,將之封裝起來。這個原則意昧著兩點:
1) 一個可變性不應當散落在代碼的很多角落里,而應當被封裝到一個對象里面。同一種可變性的不同表象意昧著同一個繼承等級結構中的具體子類。
繼承就當被看作是封裝變化的方法,而不應當被認為是從一般的對象生成特殊對象的方法。
2) 一種可變性不應當與另一種可變性混合在一起。(所有類圖的繼承結構一般不會超過兩層,不然就意昧著將兩種不同的可變性混合在了一起。)
這個原則是總的原則,其它幾條是這個原則的手段和工具。
2、里氏替代原則(Liskov Substitution Principle,或者LSP);
如果對于每一個類型為T1的對象o1,都有類型為T2的對象o2,使得以T1定義的所有程序P在所有的對象o1都代換成o2時,程序P的行為沒有變化,那么類型T2是類型T1的子類型。
換言之,一個軟件實體如果使用的是一個基類的話,那么一定適用于其子類,而且它根本不能察覺出基類對象和子類對象的區別。
反過來代換不成立。
3、依賴倒轉原則(Dependency Inversion Principle,或者DIP);
要依賴于抽象,不要依賴于具體。
開閉原則是目標,而達到這一目標的手段是依賴倒轉原則。
抽象層次包含的是應用系統的商務邏輯和宏觀的、對整個系統來說重要的戰略性決定,是必然性的體現,那么抽象層次就應當是較為穩定的,應當是復用的重點;也應當是維護的重點;而具體層次則含有一些次要的與實現有關的算法和邏輯,以及戰術性的決定,帶有相當大的偶然性選擇。具體層次的代碼是會經常有變動的,不能避免出現錯誤。
4、接口隔離原則(Interface Segregation Principle,或者ISP);
使用多個專門的接口比使用單一的總接口要好。
換言之,從一個客戶類的角度講:一個類對另一個類的依賴性應當是建立在最小的接口上的。
接口隔離原則與迪米特法則(下面講到)都是對一個軟件實體與其他的軟件實體的通信限制。迪米特原則要求盡可能地限制通信的寬度和深度,接品隔離原則要求通信的寬度盡可能地窄。這樣做的結果使一個軟件系統在功能擴展過程當中,不會將修改的壓力傳遞到其他對象。
一個接口相當于劇本中的一種角色,而此角色在一個舞臺上由哪一個演員來演則相當于接口的實現。因此,一個接口應當簡單地代表一個角色,而不是多個角色。如果系統涉及到多個角色的話,那么每一個角色都應當由一個特定的接口代表。
5、組合/聚合復用原則(Composition/Aggregation Principle,或者CARP);
組合/聚合原則就是在一個新的對象里面使用一些已有的對象,使之成為新對象的一部分;新的對象通過向這些對象的委派達到得復用已有功能的目的。
要盡量使用組合/聚合,盡量不要使用繼承。
6、迪米特法則(Law of Demeter,或者LoD);
一個軟件實體應當盡可能少的與其他實體發生相互作用。模塊之間的交互要少。這樣做的結果是當系統的功能需要擴展時,會相對更容易地做到對修改的關閉。一個對象應當對其他對象有盡可能少的了解。
7、單一職責原則(Single Responsibility Principle,或者SRP)
在設計中為每種職責設計一個類,彼此保持正交,互不干涉。這個原則比較容易理解,這里不在多說。
?????小結
?????當我們掌握了C#的語法,當我們了解了面向對象的封裝、繼承、多態等特性,當我們可以用各種框架與技術構建桌面以及Web應用時,這并不意味著我們可以寫出面向對象的程序,不意味著我們可以很好的實現代碼復用,彈性維護,不意味著我們可以實現在維護、擴展基礎上的代碼復用。使用面向對象語言開發的程序不一定是面向對象的,使用面向過程的語言開發的程序也不一定不是面向對象的。要想開發出一個具有可維護性和可復用性的軟件系統,那是需要優秀的設計和長時間的運行才能完成的,其實我們可以觀察一下,任何一個優秀的軟件產品都是經過長時間的設計,運行,維護,修改等最后才成為成功的產品,版本上也在不斷的更新。衡量一個軟件開發者是不是一個好的軟件開發者,不是看他是否實現了軟件的必要功能,而是要看你的軟件在滿足功能需求的情況下是否做到了復用性和可擴展性,這對于一個大型系統尤其重要。我們不要靜止的看待一個軟件,而一定要把軟件過程放在時間軸上來觀察與設計它,只有放在時間軸上經得住考驗的軟件系統才是成功的。軟件的復用性和可擴展性對于大型系統是必要的,我們在設計自己的軟件系統時,甚至在編寫代碼時更需要考慮一下這樣做是否遵循了系統設計的原則,是否有利于系統的可維護性和可復用性,是否達到了常說的“高內聚低耦合”呢?設計模式正是解決這一問題的王道。
?????從下文開始我們將結合實例對于GoF23種設計模式進行一一講解。
?????Welcome to share your idea,thank you!歡迎分享您的想法,謝謝!
?????大家一起學面向對象設計模式系列 索引貼
轉載于:https://www.cnblogs.com/Thriving-Country/archive/2009/03/13/1408030.html
總結
以上是生活随笔為你收集整理的大家一起学面向对象设计模式系列Chapter 02 软件设计的基本原则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL SERVER 优化 50法
- 下一篇: 任天堂新音樂遊戲上市