設計模式
設計模式的概念
設計模式最初用于建筑領域的設計中。
軟件的設計模式,又稱設計模式,是一套被反復使用,多數人知道的,經過分類編目的,代碼設計經驗的總結。
它描述了在軟件設計過程中的一些不斷重復發生的問題,以及如何解決這些問題。
它是解決特定問題的一系列套路,是前輩們的代碼設計經驗的總結,具有一定的普遍性,可以反復使用。
設計模式的作用
設計模式的本質是面向對象設計原則的實際運用,是對類的封裝性,繼承性和多態性記憶類的關聯關系和組合關系的充分理解。
正確使用設計模式具有以下優點:
- 可以提高程序員的思維能力,編程能力和設計能力。
- 使程序設計更加標準化,使軟件開發效率大大提高。
- 使設計的代碼可重用性高,可讀性強,可靠性高,靈活性好,可維護性強。
- 能夠更好的去理解源碼架構。
如果需要設計大型項目架構,必須考慮增加新功能的代碼變動成本,要保證新加入的功能不影響以前的功能。
建模語言
統一建模語言(Unifiled Modeling Language)簡稱UML是一種用于軟件系統分析和設計的語言工具,用于幫助軟件開發人員進行思考和記錄思路的結果。
UML圖:通過不同的圖形和符號來描述軟件模型以及各個元素之間的關系。
類圖:展示模型的靜態結構,特別是模型中存在的類,類的內部結構以及它們與其他類的關系等。
類
類是指具有相同屬性,方法,關系的對象的抽象,封裝了數據和行為,是OOP(面向對象程序設計)的基礎,具有封裝性,繼承性和多態性等三大特性。
在UML中,類使用包含類名,屬性和操作且帶有分割線的矩形表示。
- 類名是一個字符串,例如:Student,Teacher
- 屬性是指類的特性,即類的成員變量。
UML按照以下格式:
[可見性]屬性名:類型[=默認值]
例如:-name:String
注意:“可見性”表示該屬性對類外的元素是否可見,包括公有(Public)、私
有(Private)、受保護(Protected)和朋友(Friendly)4 種,在類圖中分別
用符號+、-、#、~表示。
3.操作是類的任意一個實例對象都可以使用的行為,是類的成員方法
UML按照以下格式:
[可見性]名稱(參數列表)[:返回類型]
例如:+display():void。
學生類的UML表示如下:
接口
接口是一種特殊的類,它具有類的結構但不可被實例化,只可以被子類實現。
它包含抽象操作,但不包含屬性。它描述了類或組件對外可見的
UML表示如下:
類之間的關系
在軟件系統中,類不是孤立的,類與類之間存在各種關系。根據類與類之間的耦合度從弱到強排列,UML中類圖有以下幾種關系:
依賴關系,關聯關系,聚合關系,組合關系,泛化關系,實現關系。
其中泛化和實現的耦合度相等,它們是最強的。
1.依賴關系
依賴關系指的是一種臨時使用的關聯,是耦合度最低的關系。
某個類的方法通過局部變量,方法的參數或者對靜態方法的臨時調用來訪問另一個類(被依賴類)中的某些方法來完成一些職責。
在UML中依賴關系使用帶箭頭的虛線表示,剪頭從使用類指向被依賴類。
下圖展示人通過手機的語言傳送方法打電話
2.關聯關系
是對象之間的引用關系。
用于表示一類對象與另一類對象之間的聯系,如老師和學生,師傅和徒弟等。
關聯關系是類與類之間最常用的一種關系,氛圍一般關聯關系,聚合關系和組合關系。
關聯可以分為單向關聯,雙向關聯,自關聯。
單向關聯:
雙向關聯:
所謂雙向關聯就是雙方各自持有對方類型的成員變量。
自關聯:
3.聚合關系
聚合關系是關聯關系的一種,是強關聯關系,是整體和部分之間的關系。
聚合關系通過成員對象實現,其中成員對象時整體對象的一部分,但成員對象可脫離整體對象獨立存在。例如學校和老師的關系,若學校消失老師獨立存在
聚合關系在UML圖中用空心菱形的實線表示,菱形指向整體。
4.組合關系
組合表示類之間的整體與部分的關系,但它是一種更強烈的聚合關系。
在組合關系中,整體對象可以控制部分對象的生命周期,一旦整體對象不存在了,部分對象也將不復存在,部分對象無法脫離整體對象而存在。例如頭和嘴的關系。
在UML圖中組合關系使用實心菱形實線表示:
5.繼承關系
繼承關系是對象之間耦合度最大的一種關系,表示一般與特殊的關系,是父類與字類之間的關系,是一種繼承關系,是is-a的關系。
在UML圖中,繼承關系使用空心三角剪頭實線表示,剪頭從子類指向父類,在代碼實現時,使用面向對象的繼承機制來實現繼承關系。
例如下圖:
6.實現關系
實現關系是接口和實現類之間的關系。
在這種關系中,類實現了接口,類中的操作實現了接口中所聲明的所有的抽象操作。
在UMl類圖中,實現關系使用帶空心三角剪頭的虛線表示
如下圖:
面向對象設計原則
單一職責
單一職責原則是最簡單的面向對象設計原則,用于控制類的粒度大小。
對于單一職責原則,可以理解為一個類只負責一個功能領域中的相應職責,即一個類不要負責太多雜亂的工作。
在軟件系統中,如果一個類繼承的職責過多,就等于把這些職責耦合在一起,一個職責的變化可能會削弱或已知這個類完成其他職責的能力,這種耦合會導致一個脆弱的設計。
單一職責原則是實現高內聚,低耦合的指導方針。
以項目開發為例,如果項目組成員每個人的職責都很明確,可以專心開發自己負責的板塊,那么項目成功就會相對較高,反之則較低
開閉原則
開閉原則指的是對拓展開放,對修改封閉。
在程序需要進行拓展時,不能去修改原有的代碼,實現一個熱插拔的效果。
為了使程序的拓展性好,易于維護和升級。想要達到這樣的效果,我們需要使用接口和抽象類。
因為抽象靈活性好,適應性廣,只要抽象的合理,可以基本保持軟件架構的穩定。
而軟件中易變的細節可以中抽象派生出來的實現類來拓展。
依賴倒置
上層模塊不應該依賴低層模塊,它們都應該依賴于抽象,抽象不應該依賴于細節,細節應該依賴于抽象。
核心思想:面向接口,不面向實現編程。
抽象指的是抽象類或接口,細節指的是實現類。
使用接口或抽象類制定好規范和契約,不設計任何具體的操作,把展現細節的人物交給它們的實現類完成。
依賴倒置原則是實現開閉原則的重要途徑之一,降低了類與類模塊之間的耦合。
接口隔離
使用多個接口,而不使用單一的接口,不強迫新功能實現不同的方法。
組合/聚合復用原則
優先使用組合/聚合,使系統更加靈活,其次才考慮繼承,達到復用的目的.
一般而言,如果兩個類之間是"Has-A"關系應使用組合或聚合,如果是"Is-A"關系使用繼承
里氏替換原則
使用繼承時若父類的方法是非抽象的,那么子類繼承父類并對父類中的非抽象方法進行重寫時要注意,若使用父類的時候換成子類對象,由于子類對象重寫的父類方法,從而導致有可能實現不相同導致結果不對
里氏替換原則的提出
1987年麻省理工計算機科學實驗室思里科夫女士在面向對象技術的高峰會議上發表的文章《數據抽象和層次》中提出,她表明:擠成必須保證超類所擁有的性質在子類中仍然成立。
里氏替換原則主要闡述了有關擠成的一些原則,也就是什么時候應該使用繼承,什么時候不應該使用繼承,使用繼承時應該避免哪些問題。
里氏替換原則的定義
所有使用父類的地方必須能透明地使用其子類的對象。
在軟件中將一個基類對象替換成它的子類對象時程序將不會產生任何錯誤和異常
簡單來說,任何基類可以出現的地方,字類一定可以出現,所以字類可以拓展父類的中能,但不能改變父類原有的功能。
也就是說子類繼承父類時,除了添加新的方法完成新增功能外,盡量不要重寫父類方法,如果重寫父類的方法,程序運行會發生出錯概率。如果一定要用多態,那么父類可以設計成抽象接口。
歷史替換原則的作用
它是功能正確性的保證。
加強程序的健壯性,提高程序的維護性降低需求變更時引入的風險
迪米特原則
只和“朋友”交談,不和“陌生人”說話。
兩個類之間如果沒有直接的聯系,那么就不要相互之間調用,可以通過一個第三方進行調用。
例如:明星,公司,粉絲,經紀人之間的交流
可以通過經紀人和明星,公司,粉絲分別進行接觸,交流
總結
設計原則的核心思想
找出應用中可能需要變化之處,獨立出來,不要和不需要變化的代碼混在一起
針對抽象編程,而不是針對程序編程
為了交互對象的松耦合設計而努力
遵循設計原則;為了讓程序高內聚,低耦合