1. 程式人生 > >《大話設計模式》學習筆記

《大話設計模式》學習筆記

-s proxy 種類型 引用 實例化 印刷 cor strong ext

今天睡醒後就拿起《大話設計模式》這本書來看,更是看的一天飯也沒吃。我對於設計模式只是一知半解,看了之後感覺受益匪淺。在此做個小筆記。也強烈建議像我這樣的萌新去看看。

前言

首先復習一下向對象編程的優點:可維護,可復用,可擴展,靈活性好

面向對象的好處:(原文)

之後當我學習了面向對象的分析設計編程思想,開始考慮通過封裝、繼承、多態把程序的耦合度降低,傳統印刷術的問題就在於
所有字都刻在同一版面上造成耦合度太高太高所致,開始同設計模式使得程序更加的靈活,容易修改,並且易於復用。

(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依賴註入) ③接口聲明依賴對象(接口註入) 使用原則: 依賴倒置原則的本質就是通過抽象(接口或抽象類)使各個類或模塊的實現彼此獨立,不互相影響,實現模塊間的松耦合,我們怎麽在項目中使用這個規則呢?只要遵循以下的幾個規則就可以: ①每個類盡量都有接口或抽象類,或者抽象類和接口兩者都具備 ②變量的表面類型盡量是接口或者是抽象類 ③任何類都不應該從具體類派生(只要不超過兩層的繼承是可以忍受的) ④盡量不要復寫基類的方法

《大話設計模式》學習筆記