《大話設計模式》學習筆記
今天睡醒後就拿起《大話設計模式》這本書來看,更是看的一天飯也沒吃。我對於設計模式只是一知半解,看了之後感覺受益匪淺。在此做個小筆記。也強烈建議像我這樣的萌新去看看。
前言
首先復習一下向對象編程的優點:可維護,可復用,可擴展,靈活性好。
面向對象的好處:(原文)
之後當我學習了面向對象的分析設計編程思想,開始考慮通過封裝、繼承、多態把程序的耦合度降低,傳統印刷術的問題就在於
所有字都刻在同一版面上造成耦合度太高太高所致,開始同設計模式使得程序更加的靈活,容易修改,並且易於復用。
(1).<簡單工廠模式>(書本例子:計算器的實現)
主要是利用繼承的特性,
父類對象的引用指向一個子類的對象。
工廠根據輸入要求,實例化出合適的子類對象返回給父類。
public class AnimalFactory { private Animal anima; public Animal getAnimal(String name) { if(name.equals("cat")) { anima = new Cat();//繼承Animal類 } else { anima = new Dog();//繼承Animal類
}
return anima; }
}
//使用AnimalFactory工廠獲取實例對象Animal anima = AnimalFactory.getAnimal("cat"); //調用anima的方法
anima.yell();
定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。
(2).<策略模式Strategy>(書本例子:商場收銀軟件)
定義:它定義了算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化,不會影響到使用算法的客戶。
策略上下文 類
public class StrategyContext { private Method method; public StrategyContext(Method method) {//抽象策略類this.method = method; } public String getTotle() { method.getTotleMoney();//不同的實現類有不同的算法 } }
客戶端調用
StrategyContext methodContext = null; if(?) { methodContext = new StrategyContext(new CashNormal());//CashNormal繼承了Method抽象策略類 } else { methodContext = new StrategyContext(new CashRebate());//CashRebate繼承了Method抽象策略類 } animaContext.getTotleMoney();//算法
策略模式經常與簡單工廠模式一起使用
策略模式是一種定義一系列算法的方法,從概念上來看,所有這些算法完成的都是相同的工作,只是具體實現不同,他可以以相同的方式調用所有的算法,減少了各種算法類與使用算法類之間的耦合
策略模式封裝了變化
(3).<裝飾模式Decorator>(書本例子:怎麽穿衣打扮)
定義:動態地給一個對象添加一些額外的職責,就增加功能來說,裝飾模式比生成子類更為靈活。
類似與一個對象調用鏈。所有Decorator類都繼承同一個類。
public class PersonA extends Person{ private Person component; public void decorate(Person component) { this.component = component; } @Override public void show() { System.out.println("PersonA: 在裝飾類的show方法多加一句打印"); component.show(); } }
Person p1 = new Person(); PersonA p2 = new PersonA(); PersonB p3 = new PersonB(); p2.decorate(p1); p3.decorate(p2); p3.show();使用場景: ● 需要擴展一個類的功能,或給一個類增加附加功能。 ● 需要動態地給一個對象增加功能,這些功能可以再動態地撤銷。 ● 需要為一批的兄弟類進行改裝或加裝功能,當然是首選裝飾模式。
(4).<代理模式Proxy>(書本例子:替別人送情書)
定義:為其他對象提供一種代理以控制對這個對象的訪問 。
代理類 和 被代理類 實現同一個主題接口,
代理類中包含被代理類的實例,其他類調用代理類的代理方法
public class PersonA extends Person{ private PersonB personB; @Override public void proxy() { if(personB == null) { personB = new PersonB(); } personB.proxy(); } }
應用場景:
1.遠程代理,也就是為一個對象在不同的地址空間提供局部代理。這樣可以隱藏一個對象存在於不同地址空間的事實。
2.虛擬代理,根據需要創建開銷很大的對象。通過它來存放實例化需要很長時間的真實對象。
3.安全代理,用來控制真實對象訪問時的權限,一般用於對象應該有不同的訪問權限的時候。
4.智能指引,是指當調用真實的對象時,代理處理另外一些事。
(4).<工廠方法模式>(書本例子:學雷鋒做好事)
定義:
設計原則:
(1)單一職責原則(SRP):就一個類而言,應該僅有一個引起它變化的原則。
接口一定要做到單一職責,類的設計盡量做到只有一個原因引起變化。
單一職責原則有什麽好處: ● 類的復雜性降低,實現什麽職責都有清晰明確的定義; ● 可讀性提高,復雜性降低,那當然可讀性提高了; ● 可維護性提高,可讀性提高,那當然更容易維護了; ●變更引起的風險降低,變更是必不可少的,如果接口的單一職責做得好,一個接口修改只對相應的實現類有影響,對其他的接口無影響,這對系統的擴展性、維護性都有非常大的幫助。
(2)開放-封閉原則(OCP):就說軟件實體(類、模塊、函數等等)應該可以擴展,但是不可修改。
對於擴展是開放的,對於更改是封閉的
怎樣的設計才能面對需求的改變卻可以保持相對穩定,從而使得系統可以在第一個版本以後不斷推出新的版本呢?
變化的三種類型: ①邏輯變化 只變化一個邏輯,而不涉及其他模塊,比如原有的一個算法是a*b+c,現在需要修改為a*b*c,可以通過修改原有類中的方法的方式來完成,前提條件是所有依賴或關聯類都按照相同的邏輯處理。 ②子模塊變化 一個模塊變化,會對其他的模塊產生影響,特別是一個低層次的模塊變化必然引起高層模塊的變化,因此在通過擴展完成變化時,高層次的模塊修改是必然的。 ③可見視圖變化 可見視圖是提供給客戶使用的界面,如JSP程序、Swing界面等,該部分的變化一般會引起連鎖反應(特別是在國內做項目,做歐美的外包項目一般不會影響太大)。可以通過擴展來完成變化,這要看我們原有的設計是否靈活。 (3)依賴倒裝原則(DEP): A:高層模塊不應該依賴底層模塊。兩個都應該依賴抽象。 B:抽象不應該依賴細節。細節應該依賴抽象。 結合 裏氏代換原則(LSP):子類型必須能夠替換掉它們的父類型。 依賴倒置原則在java語言中的體現: ①模塊間的依賴通過抽象發生,實現類之間不發生直接的依賴關系,其依賴關系是通過接口或抽象類產生的; ②接口或抽象類不依賴於實現類; ③實現類依賴接口或抽象類。 依賴的三種寫法: ①構造函數傳遞依賴對象(構造函數註入) ②Setter方法傳遞依賴對象(setter依賴註入) ③接口聲明依賴對象(接口註入) 使用原則: 依賴倒置原則的本質就是通過抽象(接口或抽象類)使各個類或模塊的實現彼此獨立,不互相影響,實現模塊間的松耦合,我們怎麽在項目中使用這個規則呢?只要遵循以下的幾個規則就可以: ①每個類盡量都有接口或抽象類,或者抽象類和接口兩者都具備 ②變量的表面類型盡量是接口或者是抽象類 ③任何類都不應該從具體類派生(只要不超過兩層的繼承是可以忍受的) ④盡量不要復寫基類的方法
《大話設計模式》學習筆記