[java設計模式]工廠設計模式,給物件一個合法的生產渠道。

小杆子發表於2021-01-24

引言

在實際的專案中,隨著我們的物件越來越多。管理的難度也越來越大。這時候怎麼辦呢?使用Spring容器呀!沒錯Spring容器也是用到了工廠設計模式。所以,我們今天就來學習一下工廠設計模式。

何為工廠設計模式?
根據名稱來理解,什麼是工廠?工廠就是有一堆流水線,來生產某一類的產品。假設:我們現在需要一瓶洗髮水,來呵護一下我們秀美的頭髮。於是我們親自動手做了一瓶:guardsman:海飛絲洗髮水。用了一段時間之後,我們發現自己的頭髮越來越少。這個時候,我們繼續一瓶 :suspect:霸王防脫洗髮水,我們總不能每次都自己手動做一瓶,費時費力,還不見的效果好。那怎麼辦呢?當然讓工廠去負責生產洗髮水,我們直接透過購買獲得就OK。

工廠設計模式應用場景
在寫程式中,我們需要去建立某一類的一系列物件。比如:如上述,我們需要各種各樣的洗髮水,它們都同屬於洗髮水一類。

工廠設計模式的特徵:

  • 呼叫者想建立物件,只需要呼叫對應的API即可。
  • 擴充套件性強,需要增加一個產品,只需要擴充套件一個工廠類即可。
  • 遮蔽產品的具體實現,呼叫者只關心產品的介面。

常見的工廠設計模式:

  1. 簡單工廠
  2. 工廠方法
  3. 抽象工廠

簡單工廠
簡單工廠,就是透過邏輯判斷,返回相應的物件。嚴格意義來講,如果我們要進行擴充套件的時候違背了開閉原則。工作中,不建議使用,耦合性太強了。

/**
 * 洗髮水產品的介面
 */
interface Shampoo {
    //... 一些洗髮水的特性
}

/**
 * 海飛絲的洗髮水具體實現
 */
class HeadShouldersShampoo implements Shampoo {
    //... 海飛絲洗髮水的特性
}

/**
 * 霸王洗髮水的具體實現
 */
class BAWANGShampoo implements Shampoo {
    //... 霸王洗髮水的特性
}

/**
 * 清揚洗髮水的具體實現
 */
class ClearShampoo implements Shampoo {
    //... 清揚洗髮水的特性
}

/**
 * 洗髮水工廠
 */
class ShampooFactory {

    // 提供對外獲取Shampoo的API
    public static Shampoo getShampoo(String shampooName) {
        // 獲取海飛絲洗髮水物件
        if ("HeadShouldersShampoo".equalsIgnoreCase(shampooName)) {
            return new HeadShouldersShampoo();
            // 獲取霸王洗髮水物件
        } else if ("BAWANGShampoo".equalsIgnoreCase(shampooName)) {
            return new BAWANGShampoo();
            // 獲取清揚洗髮水物件
        } else if ("ClearShampoo".equalsIgnoreCase(shampooName)) {
            return new ClearShampoo();
        }
        return null;
    }
}

/**
 * @ClassName : SimpleFactory
 * @Description : 簡單工廠
 */
public class SimpleFactory {
    public static void main(String[] args) {
        // 獲取海飛絲洗髮水物件
        Shampoo headShouldersShampoo = ShampooFactory.getShampoo("HeadShouldersShampoo");
        if (headShouldersShampoo instanceof HeadShouldersShampoo){
            System.out.println("獲取海飛絲洗髮水物件成功");
        }

        // 獲取霸王洗髮水物件
        Shampoo bawangShampoo = ShampooFactory.getShampoo("BAWANGShampoo");
        if (bawangShampoo instanceof BAWANGShampoo){
            System.out.println("獲取霸王洗髮水物件成功");
        }

        // 獲取清揚洗髮水物件
        Shampoo clearShampoo = ShampooFactory.getShampoo("ClearShampoo");
        if (clearShampoo instanceof ClearShampoo){
            System.out.println("獲取清揚洗髮水物件成功");
        }
    }
}

工廠方法
我們依然站在生活的角度去理解,簡單工廠,就是一個工廠,來生產各種各樣的洗髮水。但現實生活中,這樣有不操作是不現實的。我們一般會用一個工廠來生產海飛絲洗髮水,一個工廠來生產霸王洗髮水,一個工廠來生產清揚洗髮水。此時,我們如果要新增一個品牌的洗髮水,只需要增加一個工廠就好了。

// 洗髮水介面
interface Shampoo{
    // ... 洗髮水共有的特性
}

/**
 * 海飛絲的洗髮水具體實現
 */
class HeadShouldersShampoo implements Shampoo {
    //... 海飛絲洗髮水的特性
}

/**
 * 霸王洗髮水的具體實現
 */
class BAWANGShampoo implements Shampoo {
    //... 霸王洗髮水的特性
}

/**
 * 清揚洗髮水的具體實現
 */
class ClearShampoo implements Shampoo {
    //... 清揚洗髮水的特性
}

/**
 * 抽象出洗髮水工廠共有的特性
 */
interface ShampooFactory{
    // 生產一瓶洗髮水
    Shampoo getShampoo();
}

/**
 * 海飛絲洗髮水工廠,主要負責生產海飛絲品牌的洗髮水
 */
class HeadShouldersShampooFactory implements ShampooFactory{

    @Override
    public Shampoo getShampoo() {
        return new HeadShouldersShampoo();
    }
}

/**
 * 霸王洗髮水工廠,主要負責生產霸王品牌的洗髮水
 */
class BAWANGShampooFactory implements ShampooFactory{
    @Override
    public Shampoo getShampoo() {
        return new BAWANGShampoo();
    }
}

/**
 * 清揚洗髮水工廠,主要負責生產清揚品牌的洗髮水
 */
class ClearShampooFactory implements ShampooFactory{

    @Override
    public Shampoo getShampoo() {
        return new ClearShampoo();
    }
}

/**
 * @ClassName : FactoryMethod
 * @Description : 工廠方法
 */
public class FactoryMethod {

    public static void main(String[] args) {
        // 獲取海飛絲洗髮水,首先獲取海飛絲的工廠,在獲取海飛絲洗髮水物件。
        // 這裡肯定有小夥伴會疑惑,寧願 new 一個海飛絲工廠,為何不直接new 海飛絲物件呢?
        // 其實結合單例設計模式,這個你可以把海飛絲工廠寫成單例,就不會重複的new 海飛絲工廠了。
        Shampoo shampoo = new HeadShouldersShampooFactory().getShampoo();
        if (shampoo instanceof HeadShouldersShampoo){
            System.out.println("獲取海飛絲洗髮水物件成功");
        }

        // 獲取霸王洗髮水物件
        Shampoo shampoo1 = new BAWANGShampooFactory().getShampoo();
        if (shampoo1 instanceof  BAWANGShampoo){
            System.out.println("獲取霸王洗髮水物件成功");
        }

        // 獲取清揚洗髮水物件
        Shampoo shampoo2 = new ClearShampooFactory().getShampoo();
        if (shampoo2 instanceof ClearShampoo){
            System.out.println("獲取清揚洗髮水物件成功");
        }
    }
}

抽象工廠
抽象工廠,這個名字起的都很抽象。不要好理解。比較官方一點的解釋:提供一個建立一系列相關或相互依賴物件的介面,而無需指定它們具體的類。讀起來都有點拗口。那就講一下本博主怎麼去理解?我們依然拿來生產一瓶洗髮水為例子。一瓶洗髮水,大致是由包裝和液體組成的,在實際的生產工作中,我們不可能序列的去生產,這樣太浪費時間了。於是乎,我們為了生產一瓶洗髮水,就最少開兩條流水線,一條生產液體,一條生產瓶子,又因為大部分的洗髮水,都是由和這個兩部分組成的,所以我們需要將生產液體和生產瓶子抽象出來,由每個品牌洗髮水自己的流水線來實現。

import java.util.List;

/**
 * 定義洗髮水介面
 */
interface Shampoo {
    // 設定洗髮水的液體
    void setLiquid();

    // 設定洗髮水的瓶子
    void setBox();
}

/**
 * 海飛絲的洗髮水具體實現
 */
class HeadShouldersShampoo implements Shampoo {
    @Override
    public void setLiquid() {
        System.out.println("設定海飛絲洗髮水有液體");
    }

    @Override
    public void setBox() {
        System.out.println("設定海飛絲洗髮水的包裝");
    }
    //... 海飛絲洗髮水的特性
}

/**
 * 霸王洗髮水的具體實現
 */
class BAWANGShampoo implements Shampoo {
    @Override
    public void setLiquid() {
        System.out.println("設定霸王洗髮水液體");
    }

    @Override
    public void setBox() {
        System.out.println("設定霸王洗髮水的包裝");
    }
    //... 霸王洗髮水的特性
}

/**
 * 清揚洗髮水的具體實現
 */
class ClearShampoo implements Shampoo {
    @Override
    public void setLiquid() {
        System.out.println("設定清揚洗髮水液體");
    }

    @Override
    public void setBox() {
        System.out.println("設定清揚洗髮水的包裝");
    }
    //... 清揚洗髮水的特性
}

/**
 * 洗髮水的液體介面,由各個品牌來實現
 */
interface Liquid {
}

/**
 * 海飛絲洗髮水的具體實現類
 */
class HeadShouldersShampooLiquid implements Liquid {
}

/**
 * 霸王洗髮水液體的具體實現類
 */
class BAWANGShampooLiquid implements Liquid {
}

/**
 * 清揚洗髮水液體的具體實現類
 */
class ClearShampooLiquid implements Liquid {
}

/**
 * 洗髮水包裝介面,有具體品牌的子類來實現
 */
interface Box {
}

/**
 * 海飛絲的包裝
 */
class HeadShouldersShampooBox implements Box {
}

/**
 * 霸王的包裝
 */
class BAWANGShampooBox implements Box {
}

/**
 * 清揚的包裝
 */
class ClearingShampooBox implements Box {
}

/**
 * 工廠介面
 */
interface ShampooFactory {
    // 生產液體的流水線。
    Liquid productionLiquid();

    // 生產盒子的流水線。
    Box productionBox();

    // 生產洗髮水,將生產的液體和流水線組裝起來。
    Shampoo getShampoo(Liquid liquid, Box box);
}

/**
 * 海飛絲洗髮水的工廠
 */
class HearingShampooFactory implements ShampooFactory {

    @Override
    public Liquid productionLiquid() {
        return new HeadShouldersShampooLiquid();
    }

    @Override
    public Box productionBox() {
        return new HeadShouldersShampooBox();
    }

    @Override
    public Shampoo getShampoo(Liquid liquid, Box box) {
        return new HeadShouldersShampoo();
    }
}

/**
 * 霸王洗髮水的工廠
 */
class BAWANGShampooFactory implements ShampooFactory {

    @Override
    public Liquid productionLiquid() {
        return new BAWANGShampooLiquid();
    }

    @Override
    public Box productionBox() {
        return new BAWANGShampooBox();
    }

    @Override
    public Shampoo getShampoo(Liquid liquid, Box box) {
        return new BAWANGShampoo();
    }
}

/**
 * 清揚洗髮水工廠
 */
class ClearingShampooFactory implements ShampooFactory {

    @Override
    public Liquid productionLiquid() {
        return new ClearShampooLiquid();
    }

    @Override
    public Box productionBox() {
        return new ClearingShampooBox();
    }

    @Override
    public Shampoo getShampoo(Liquid liquid, Box box) {
        return new ClearShampoo();
    }
}

/**
 * @ClassName : abstractFactory 抽象工廠
 * @Description : 抽象工廠
 */
public class abstractFactory {
    public static void main(String[] args) {
        // 生產一瓶海飛絲的洗髮水
        // 建立一個海飛絲的工廠
        HearingShampooFactory hearingShampooFactory = new HearingShampooFactory();
        // 生產海飛絲洗髮水液體
        Liquid liquid = hearingShampooFactory.productionLiquid();
        // 生產海飛絲的包裝
        Box box = hearingShampooFactory.productionBox();
        if (box instanceof HeadShouldersShampooBox && liquid instanceof HeadShouldersShampooLiquid) {
            Shampoo shampoo = hearingShampooFactory.getShampoo(liquid, box);
            if (shampoo instanceof HeadShouldersShampoo) {
                System.out.println("生產海飛絲洗髮水成功");
            }
        }

        // 生產一瓶霸王的洗髮水
        // 建立一個霸王的工廠
        BAWANGShampooFactory bawangShampooFactory = new BAWANGShampooFactory();
        // 生產霸王洗髮水液體
        Liquid liquid1 = bawangShampooFactory.productionLiquid();
        // 生產霸王的包裝
        Box box1 = bawangShampooFactory.productionBox();
        if (liquid1 instanceof BAWANGShampooLiquid && box1 instanceof BAWANGShampooBox) {
            Shampoo shampoo = bawangShampooFactory.getShampoo(liquid1, box1);
            if (shampoo instanceof BAWANGShampoo) {
                System.out.println("生產霸王洗髮水成功");
            }
        }

        // 生產一瓶清揚洗髮水
        // 建立一個清揚洗髮水工廠
        ClearingShampooFactory clearingShampooFactory = new ClearingShampooFactory();
        // 生產清揚洗髮水液體
        Liquid liquid2 = clearingShampooFactory.productionLiquid();
        // 生產清揚洗髮水瓶子
        Box box2 = clearingShampooFactory.productionBox();
        if (liquid2 instanceof ClearShampooLiquid && box2 instanceof ClearingShampooBox) {
            Shampoo shampoo = clearingShampooFactory.getShampoo(liquid2, box2);
            if (shampoo instanceof ClearShampoo) {
                System.out.println("生產清揚洗髮水成功");
            }
        }
    }
}

工廠設計模式,差不多就這些了。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章