1、設計模式相關概念
(1)重要性
設計模式(design pattern)對軟件設計中普片存在的問題所提出的解決方案(不拘泥於某種語言),可以增強項目的擴展性、維護性,因爲設計模式不是爲了軟件的功能的實現,而是站在軟件的設計的角度
(2)目的
增強可維護性、重用性、靈活性、可靠性(增加或減少新功能後對原有的功能沒有影響),實現高內聚低耦合
2、設計模式的七大原則
(1)概念
設計模式設計的依據
(2)七大原則
- 單一職責
例如:一個類只負責一項職責,如果一個類有多個職責,那麼在修改其中一個職責的時候可能會對其他的職責造成影響,就應該將不同的職責分配到不同的類中。
類級別:
有一個交通工具類中有一個run方法,那麼所有的交通工具都可以調用run方法,汽車、火車等,但是,飛機調用run方法可能就會不合理了,因爲飛機是在天上飛的。此時有一個解決方案就是再創建一個飛行器類,火車和汽車調用陸地上的交通工具類的run方法,飛機調用飛行器的run方法
方法級別(沒有完全遵守單一職責原則,只有在類級別的是真正的單一職責原則):
將不同的職責放到不同的類中做到的單一職責需要的改動較大,可以採用在一個類中定義不同的方法的方式實現單一職責原則,就是不同的方法實現不同的職責,使用類的同一個對象調用不同方法即可(在類中的方法足夠少的時候可以違反單一職責原則)。
好處:
降低代碼的複雜度,一個類只負責一個原則(如:權限類只負責權限相關的方法和屬性,與角色無關)
提高代碼的可讀性和可維護性
降低變更引起的風險
- 接口隔離原則
上面的接口設計存在一個問題,Class3通過接口Inter調用Class1的方法的時候只用到了前三個方法後面的兩個方法是多餘的
上面的UML圖中對接口進行了拆分,使得Class1和Class2中的方法都是Class3和Class4所需要使用的方法,這樣就符合了接口的隔離原則。也就是說一個類在通過接口調用另外一個接口的實現類的方法的時候這個實現類應該是最小的(沒有多餘的方法)
- 依賴倒轉
高層模塊不應該依賴低層模塊,二者都應該依賴其抽象
抽象不應該依賴細節,細節應該依賴抽象
中心思想是面向接口編程
例如:員工有一個接收消息的方法,這個時候此方法就需要調用Emai類中的發送Email的方法,如果還需要手機短信和微信的接收消息的方法,那麼就需要新增類並在員工類中添加方法,在調用的時候需要傳遞的是Email類的一個對象。
public String getMessage(Email email)
可以再添加一個消息發送的接口,Email、微信、手機短信類都實現這個接口,此時如果添加其它的有關消息發送的類也只需要添加一個該接口的實現類即可。客戶端在調用的時候創建相應的實現類的對象即可。
public String getMessage(IMessage messge)
依賴倒轉原則的注意事項:
低層模塊儘量要有抽象類或接口,或者兩者都有
變量的聲明類型儘量是抽象類或接口,這樣我們的變量引用和實際對象之間就存在一個緩衝(例如:字類在繼承父類的方法的時候可以重寫父類的方法,對方法的功能進行優化),利於程序的擴展和優化
繼承的時候遵循里氏替換原則
- 里氏替換
父類中有一個計算兩個數的差的方法,子類的一個計算兩個數的和的方法與父類中的方法重名了(無意中重寫了父類的方法),通常的避免此種情況發生的做法是讓原來的父類和字類都繼承一個更通俗的基類,原有的繼承關係去掉,採用依賴、聚合、組合等關係。里氏替換準則要求我們儘量不要重寫父類中的方法
也就是說將A類和B類共有的內容放到Base類中,將A和B的關係變爲依賴、聚合、組合等關係,A類和B類的耦合性就降低了
組合:B類調用A類的方法,可以在B類中創建一個A類的對象
private A a =new A();
- 開閉原則
一個軟件實體,如:類、模塊和函數應該對擴展開放(供應方),對修改關閉(使用方),用抽象構建框架,用實現擴展細節
當軟件需要變化的時候,儘量通過擴展軟件來實現變化而不是通過修改已有的代碼來實現變化
例如:定義一個圖形的抽象類,類中有一個draw方法,其它圖形可以繼承抽象類重寫draw方法,在繪製圖形的類的方法中只需要傳遞父類類型的參數(使用方是不需要改變的),當再擴展的的時候修改也是較小的。
- 迪米特法則(最少知道原則)
一個A類如果依賴(繼承、聚合等關係)於B類,要保證他們之間的耦合度儘量降低,B類除了暴漏一個public方法,不對外泄露任何信息。核心是降低類與類之間的耦合度。
如果是作爲成員變量、方法的參數或方法的返回值就稱爲直接朋友,如果出現在局部作用域就不是直接朋友
- 合成複用
儘量使用合成/聚合,而不是使用繼承