設計模式之工廠模式(Java)

設計模式系列文章:

  [1、設計模式之工廠模式](https://blog.csdn.net/sixingmiyi39473/article/details/78507513)
  2、設計模式之單例模式
  3、設計模式之代理模式
  4、設計模式之外觀模式(即門面模式)
  5、設計模式之策略模式
  6、設計模式之責任鏈模式
  7、設計模式之觀察者模式
  8、設計模式之建造者模式

本文章目錄:
一、工廠模式概念
二、簡單工廠模式
三、工廠方法模式
四、抽象工廠模式
五、總結

設計模式是一套反覆使用的、多數人知曉的、經過分類編目的、代碼設計經驗總結。使用設計模式爲了提高代碼的可重用性,讓代碼更容易被他人理解,保證代碼的可靠性。

一、工廠模式概念

用工廠方法代替new操作來得到一個實例化對象,工廠模式包括簡單工廠模式、工廠方法模式和抽象工廠模式,可以認爲簡單工廠模式是工廠方法模式的特例,抽象工廠模式是工廠方法模式的擴展。
項目中的應用:
在軟件系統中經常面臨着“對象”的創建工作,由於需求的變化,這個對象可能隨之也會發生變化,但它卻擁有比較穩定的接口。爲此,我們需要提供一種封裝機制來隔離出這個異變對象的變化,從而保持系統中其他依賴該對象的對象不隨着需求變化而變化。儘量鬆耦合,一個對象的依賴對象的變化與本身無關,具體產品與客戶端剝離,責任分割。

那麼在什麼樣的情況下我們應該記得使用工廠模式呢?大體有兩點:
1.在編碼時不能預見需要創建哪種類的實例。
2.系統不應依賴於產品類實例如何被創建、組合和表達的細節

For example,恩,以上理論晦澀難懂,舉個例子。我們就以某person吃飯爲例來說明,在食堂就餐時,某可能會選擇糉子、豆腐腦、烤腸,當然也可能會選擇其他。除了對食物類別的選擇之外,並且還有可能對食物的口味也很挑剔,可能是甜的、鹹的、還有辣的等等。這樣食堂大師傅就需要對食物的類別與食物的口味進行不同的組合以滿足不同客戶的需求此時食堂大師傅就充當了工廠的角色,顧客需要什麼,就生產什麼。
接下來,就簡單工廠模式、工廠方法模式和抽象工廠模式以在食堂吃飯爲例進行說明。

二、簡單工廠模式

工廠方法模式類圖
這裏寫圖片描述

(1)編寫食物接口:FoodInterface

package com.tong.Factory;
/**
 * @describe 食物接口
 * @author tong
 * @version 1.0 2017-11-8
 */
public interface FoodInterface {
    /**
     * 吃飯
     */
    void eating();
}

(2)食物接口FoodInterface的實現類:豆腐腦Doufunao

package com.tong.Factory;

public class Doufunao implements FoodInterface {
    /**
     * 吃豆腐腦
     */
    @Override
    public void eating() {
        System.out.println("***********吃豆腐腦***********");
    }
}

(3)食物接口FoodInterface的實現類:糉子Zongzi

package com.tong.Factory;

public class Zongzi implements FoodInterface {
    /**
     * 吃糉子
     */
    @Override
    public void eating() {
        System.out.println("*************吃糉子***********");
    }
}

(4)編寫工廠類:Canteen

package com.tong.Factory;
/**
 * @describe 食堂
 * @author tong
 * @version 1.0 2017-11-8
 */
public class Canteen {
    /**
     * 根據類的名稱來生產對象,這裏用到了反射機制
     * @param className
     * @return
     */
    public FoodInterface getFoodByClass(String className){
        try {
            FoodInterface food = (FoodInterface) Class.forName(className).newInstance();
            return food;
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}

(5)編寫Test類

package com.tong.Factory;

public class Test {
    public static void main(String[] args) {
        Canteen canteen = new Canteen();
        FoodInterface food = null;
        //吃豆腐腦
        food = canteen.getFoodByClass ("com.tong.Factory.Doufunao");
        food.eating();
        //吃糉子
        food = canteen.getFoodByClass ("com.tong.Factory.Zongzi");
        food.eating();
    }
}

(6)輸出結果:

***********吃豆腐腦***********
*************吃糉子***********

總結:當我們在需要什麼食物時,僅僅實現FoodInterface接口就可以了,客戶端新建類的類名就可以得到該食物。

三、工廠方法模式

工廠方法模式類圖
這裏寫圖片描述

工廠方法模式去掉了簡單工廠模式中工廠方法的靜態屬性,使得它可以被子類繼承。這樣在簡單工廠模式裏集中在工廠方法上的壓力可以由工廠方法模式裏不同的工廠子類來分擔。
工廠方法模式組成:
1)抽象工廠角色: 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。在java中它由抽象類或者接口來實現。
2)具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以創建對應的具體產品的對象。
3)抽象產品角色:它是具體產品繼承的父類或者是實現的接口。在java中一般有抽象類或者接口來實現。
4)具體產品角色:具體工廠角色所創建的對象就是此角色的實例。在java中由具體的類來實現。
還是以上面的例子來講,如果食物種類的繁多,如果僅僅由食堂的一個人來負責,未免有點任務繁重,這樣我們把食堂也定義爲是接口,然後由食堂具體的某一位大師傅來具體負責某一種或者幾種食物。

**
 * @describe 工廠接口
 * @author tong
 * @version 1.0 2017-11-8
 */
public interface CanteenInterface {
    void getFood();
}

/**
 * @describe 具體工廠
 * @author tong
 * @version 1.0 2017-11-8
 */
public class DoufunaoDashifu implements CanteenInterface {
    @Override
    public void getFood(){
        FoodInterface food = new Doufunao();
        food.eating();
    }
}
/**
 * @describe 具體工廠
 * @author tong
 * @version 1.0 2017-11-8
 */
public class ZongziDashifu implements CanteenInterface{
    @Override
    public void getFood(){
        FoodInterface food = new Zongzi();
        food.eating();
    }
}
/**
 * @describe 食物接口
 * @author tong
 * @version 1.0 2017-11-8
 */
public interface FoodInterface {
    /**
     * 吃飯
     */
    void eating();
}
//具體食物
public class Zongzi implements FoodInterface {
    /**
     * 吃糉子
     */
    @Override
    public void eating() {
        System.out.println("*************吃糉子***********");
    }
}
//具體食物
public class Doufunao implements FoodInterface {
    /**
     * 吃豆腐腦
     */
    @Override
    public void eating() {
        System.out.println("***********吃豆腐腦***********");
    }
}

當需要食物時時,只要按照分別對應食物、大師傅,那麼就可以被客戶使用,而不必去修改任何已有的代碼。(即當有新產品時,只要創建並基礎抽象產品;新建具體工廠繼承抽象工廠;而不用修改任何一個類)工廠方法模式是完全符合開閉原則的!

四、抽象工廠模式

抽象工廠模式類圖:
這裏寫圖片描述

先來認識下什麼是產品族: 位於不同產品等級結構中,功能相關聯的產品組成的家族。
在這裏糉子和豆腐腦分別是不同的產品樹,甜糉子和甜豆腐腦屬於一個產品族,鹹糉子和鹹豆腐腦屬於一個產品族。
可以這麼說,它和工廠方法模式的區別就在於需要創建對象的複雜程度上。而且抽象工廠模式是三個裏面最爲抽象、最具一般性的。抽象工廠模式的用意爲:給客戶端提供一個接口,可以創建多個產品族中的產品對象。
而且使用抽象工廠模式還要滿足一下條件:
1.系統中有多個產品族,而系統一次只可能消費其中一族產品
2.同屬於同一個產品族的產品以其使用。
來看看抽象工廠模式的各個角色(和工廠方法的如出一轍):
抽象工廠角色: 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。在java中它由抽象類或者接口來實現。
具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以創建對應的具體產品的對象。在java中它由具體的類來實現。
抽象產品角色:它是具體產品繼承的父類或者是實現的接口。在java中一般有抽象類或者接口來實現。
具體產品角色:具體工廠角色所創建的對象就是此角色的實例。在java中由具體的類來實現。

//抽象產品 豆腐腦
public interface Doufunao {
    void eating();
}
//具體產品
public class SaltDoufunao implements Doufunao{
    @Override
    public void eating() {
        System.out.println("************這是鹹豆腐腦***********");
    }
}
//具體產品
public class SweetDoufunao implements Doufunao {
    @Override
    public void eating() {
        System.out.println("************這是甜豆腐腦***********");
    }
}
//抽象產品 糉子
public interface Zongzi  {
    void eating();
}
//具體產品
public class SweetZongzi implements Zongzi{
    @Override
    public void eating() {
        System.out.println("************這是甜糉子***********");
    }
}
//具體產品
public class SaltZongzi implements Zongzi{
    @Override
    public void eating() {
        System.out.println("************這是鹹糉子***********");
    }
}
/**
 * @describe 抽象工廠
 * @author tong
 * @version 1.0 2017-11-8
 */
public interface FoodFactory {
    void getDoufunao();
    void getZongzi();
}
//具體工廠
public class SaltFactorry implements FoodFactory {
    @Override
    public void getDoufunao() {
        Doufunao food = new SaltDoufunao();
        food.eating();
    }
    @Override
    public void getZongzi() {
        Zongzi food = new SaltZongzi();
        food.eating();
    }
}
//具體工廠
public class SweetFactorry implements FoodFactory {
    @Override
    public void getDoufunao() {
        Doufunao food = new SweetDoufunao();
        food.eating();
    }

    @Override
    public void getZongzi() {
        Zongzi food = new SweetZongzi();
        food.eating();
    }
}

以上的抽象工廠模式,可以利用反射來改進抽象工廠及其子工廠的實現。

五、總結

工廠模式包括三種:

  • 簡單工廠模式
  • 工廠方法模式
  • 抽象工廠模式

1、簡單工廠模式
包括三個角色:工廠類角色、抽象產品類角色,具體產品類角色
使用:每增加一個新的具體產品類,都要在工廠類當中增加相應的業務邏輯和判斷邏輯,根據傳入的參數的生成相應的實例對象。適用於業務簡單的情況或者具體產品很少增加的情況,且違背了開放封閉原則。
2、工廠方法模式
包括三個角色:抽象工廠類角色、具體工廠類角色、抽象產品類角色,具體產品類角色
使用:每增加一個新的具體產品類,還要增加一個生產該產品的具體工廠類,這樣每個具體工廠負責一個具體產品實例的創建。
相對於簡單工廠類,不需要修改原工廠類,避免了違背開放封閉原則。
3、抽象工廠模式
包括三個角色:工廠類角色、具體工廠類角色。不同的抽象產品類角色(相當於產品分類),以及不同具體產品類
使用:每增加一個新的具體產品類,都要在工廠類當中增加相應的業務邏輯和判斷邏輯。適用於業務簡單的情況或者具體產品很少增加的情況。
例如:有電腦,手機兩種產品,而有小米、華爲兩個生產廠家。小米可以生產電腦和手機,華爲也可以生產電腦和手機,兩家生產不同牌子的電腦手機。

下一篇將會講解策略模式原理,歡迎閱覽 設計模式之策略模式

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