重溫設計模式(爲了找工作,在沒寫完23種模式之前,我會持續更新)

1:設計模式初探

1.1:什麼是設計模式

在軟件工程中,設計模式是對軟件設計中普遍存在的各種問題,所提出的 解決方案。
換句話說,設計模式是一套被反覆使用、多數人知曉的、經過分類的、代碼設計的 經驗的總結。使用設計模式是爲了可重用代碼,讓代碼更容易被他人理解,保證代碼可靠性。

1.2 設計模式原則

1、開閉原則(Open Close Principle)

開閉原則的意思是:對擴展開放,對修改封閉。在程序需要進行擴展的時候,不能去修改或影響原有的代碼,實現一個熱插拔的效果。簡言之,是爲了使程序的擴展性更好,易於維護和升級。想要達到這樣的效果,我們需要使用接口和抽象類。

2、里氏代換原則(Liskov Substitution Principle)

里氏代換原則是面向對象設計的基本原則之一。 里氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。里氏代換原則是繼承複用的基石,只有當子類可以替換掉基類,且軟件單位的功能不受到影響時,基類才能真正被複用,而且子類也能夠在基類的基礎上增加新的行爲。里氏代換原則是對開閉原則的補充。實現開閉原則的關鍵步驟就是抽象化,而基類與子類的繼承關係就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規範。

3、依賴倒轉原則(Dependence Inversion Principle)

這個原則是開閉原則的基礎,核心內容:針對接口編程,高層模塊不應該依賴底層模塊,二者都應該依賴抽象而不依賴於具體。

4、接口隔離原則(Interface Segregation Principle)

這個原則的意思是:使用多個隔離的接口,比使用單個龐大的接口要好。其目的在於降低耦合度。由此可見,其實設計模式就是從大型軟件架構出發,便於升級和維護軟件的設計思想。它強調低依賴、低耦合。

5、單一職責原則(Single Responsibility Principle)

類的職責要單一,不能將太多的職責放在一個類中。
可能有的人會覺得單一職責原則和前面的接口隔離原則很相似,其實不然。其一,單一職責原則原注重的是職責;而接口隔離原則注重對接口依賴的隔離。其二,單一職責原則主要約束的是類,其次纔是接口和方法,它針對的是程序中的實現和細節;而接口隔離原則主要約束接口,主要針對抽象,針對程序整體框架的構建。

6、最少知道原則(Demeter Principle)

最少知道原則也叫迪米特法則,就是說:一個實體應當儘量少的與其他實體之間發生相互作用,使得系統功能模塊相對獨立。
一個對象應該對其他對象保持最少的瞭解。類與類之間的關係越密切,耦合度越大,當一個類發生改變時,對另一個類的影響也越大。如果兩個類不必彼此直接通信,那麼這兩個類就不應當發生直接的相互作用。如果其中一個類需要調用另一個類的某一個方法的話,可以通過第三者轉發這個調用。所以在類的設計上,每一個類都應當儘量降低成員的訪問權限。

7、合成複用原則(Composite Reuse Principle)

合成複用原則就是在一個新的對象裏通過關聯關係(組合關係、聚合關係)來使用一些已有的對象,使之成爲新對象的一部分;新對象通過委派調用已有對象的方法達到複用功能的目的。簡而言之,儘量多使用 組合/聚合 的方式,儘量少使用甚至不使用繼承關係。

1.3:設計模式分類

通常來說設計模式分爲三大類:

創建型模式,共 5 種:工廠模式、抽象工廠模式、單例模式、建造者模式、原型模式。

結構型模式,共 7 種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。

行爲型模式,共 11 種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。
下面這張圖表示模式間的關係
Aaron Swartz

1.4:常用設計模式

在以後的課程中,我們會逐步講解常用的設計模式,包括 工廠模式、單例模式、適配器模式、觀察者模式等等。

2:工廠模式

2.1:什麼是工廠模式

工廠模式(Factory Pattern)的意義就跟它的名字一樣,在面向對象程序設計中,工廠通常是一個用來創建其他對象的對象。工廠模式根據不同的參數來實現不同的分配方案和創建對象。

在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,並且是通過使用一個共同的接口來指向新創建的對象。例如用工廠來創建 人 這個對象,如果我們需要一個男人對象,工廠就會爲我們創建一個男人;如果我們需要一個女人,工廠就會爲我們生產一個女人。

工廠模式通常分爲:

普通工廠模式
多個工廠方法模式
靜態工廠方法模式

2.2:普通工廠模式

剛剛我們說到,用工廠模式來創建人。先創建一個男人,他每天都 “喫飯、睡覺、打豆豆”,然後我們再創建一個女人,她每天也 “喫飯、睡覺、打豆豆”。

我們以普通工廠模式爲例,在project目錄下新建一個
FactoryTest.java。
ycsong
示例代碼如下(下面的代碼塊中是全部的代碼,實際操作中應當按註釋創建相應的類再將方法寫入對應的類中):

// 二者共同的接口
interface Human{
    public void eat();
    public void sleep();
    public void beat();
}

// 創建實現類 Male
class Male implements Human{
    public void eat(){
        System.out.println("Male can eat."); 
    }
    public void sleep(){
        System.out.println("Male can sleep.");
    }
    public void beat(){
        System.out.println("Male can beat.");
    }
} 
//創建實現類 Female
class Female implements Human{
    public void eat(){
        System.out.println("Female can eat."); 
    }
    public void sleep(){
        System.out.println("Female can sleep.");
    }
    public void beat(){
        System.out.println("Female can beat.");
    }
} 

// 創建普通工廠類
class HumanFactory{
    public Human createHuman(String gender){
        if( gender.equals("male") ){
           return new Male();
        }else if( gender.equals("female")){
           return new Female();
        }else {
            System.out.println("請輸入正確的類型!");
            return null;
        }
    }
}

// 工廠測試類
public class FactoryTest {
    public static void main(String[] args){
        HumanFactory factory = new HumanFactory();
        Human male = factory.createHuman("male");
        male.eat();
        male.sleep();
        male.beat();
    }
}

打開terminal,輸入命令編譯並運行:

javac FactoryTest.java
java FactoryTest

運行結果
ycsong

2.3:多個工廠方法模式

普通工廠模式就是上面那樣子了,那麼多個工廠方法模式又有什麼不同呢?在普通工廠方法模式中,如果傳遞的字符串出錯,則不能正確創建對象。多個工廠方法模式是提供多個工廠方法,分別創建對象。

部分示例代碼,其他與上面普通工廠模式示例代碼一樣:

// 多個工廠方法
public class HumanFactory{
    public Male createMale() {
        return new Male();
    }
    public Female createFemale() {
        return new Female();
    }
}

// 工廠測試類
public class FactoryTest {
    public static void main(String[] args){
        HumanFactory factory = new HumanFactory();
        Human male = factory.createMale();
        male.eat();
        male.sleep();
        male.beat();
    }
}

運行結果與單個工廠相同

2.4:靜態工廠模式:

將上面的多個工廠方法模式裏的方法置爲靜態的,不需要創建實例,直接調用即可。

部分示例代碼:

// 多個工廠方法
public class HumanFactory{
    public static Male createMale() {
        return new Male();
    }
    public static Female createFemale() {
        return new Female();
    }
}

// 工廠測試類
public class FactoryTest {
    public static void main(String[] args){
        Human male = HumanFactory.createMale();
        male.eat();
        male.sleep();
        male.beat();
    }
}

總結:凡是出現了大量的產品需要創建,並且具有共同的接口時,可以通過工廠方法模式進行創建。在以上的三種模式中,第一種如果傳入的字符串有誤,不能正確創建對象,第三種相對於第二種,不需要實例化工廠類,所以,大多數情況下,我們會選用第三種——靜態工廠方法模式。

2.5:工廠模式應用

你可能就問了,工廠模式工廠模式的,我咋沒見過哪兒用過啊?這這這兒,在 Java 庫裏面。根據不同的參數,getInstance() 方法會返回不同的 Calendar 對象。

java.util.Calendar - getInstance()
java.util.Calendar - getInstance(TimeZone zone)
java.util.Calendar - getInstance(Locale aLocale)
java.util.Calendar - getInstance(TimeZone zone, Locale aLocale)
java.text.NumberFormat - getInstance()
java.text.NumberFormat - getInstance(Locale inLocale)

寫 Android 的童鞋們,應該還知道 BitmapFactory , 這也是工廠模式的一種應用。

3:抽象工廠模式

3.1:什麼是抽象工廠模式

抽象工廠模式(Abstract Factory Pattern)是一種軟件開發設計模式。抽象工廠模式提供了一種方式,可以將一組具有同一主題的單獨的工廠封裝起來。如果比較抽象工廠模式和工廠模式,我們不難發現前者只是在工廠模式之上增加了一層抽象的概念。抽象工廠是一個父類工廠,可以創建其它工廠類。所以我們也叫它 “工廠的工廠”。(想想上節課的 “女媧娘娘”,這簡直就是 “女媧娘娘的親孃” 啊…)

3.2:抽象工廠的類圖

“女媧娘娘”只有一個,而我們的工廠卻可以有多個,因此在這裏用作例子就不合適了。作爲“女媧娘娘”生產出來的男人女人們,那就讓我們來當一次喫貨吧。(喫的東西總可以任性多來一點…)

現在,假設我們有 A、B 兩個廚房。每個廚房擁有的餐具和食品都不一樣,但是用戶搭配使用的方式,比如刀子和蘋果、杯子和牛奶等等,我們假設是一致的。
ycsong

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章