【創建型設計模式】工廠模式

前言(一些廢話,可以忽略)

  • 工廠模式是非常重要的一種設計模式,相比單例模式來說,更有結構上的設計,有思想上深一層的東西,但是和跟複雜的模式相比,其實也是很簡單的。
  • 網絡上有很多工廠模式的講解,如果你看得比較多,你會發現,一會這麼實現,一會那麼實現,怎麼感覺每一篇文章講得都大同小異,又感覺不太一樣,讓人很是迷糊。
  • 是的,開始的時候我也是這樣迷茫,當我繼續閱讀更多的設計模式的時候,恍然大悟。這不就是大師打拳的境界麼,神似而形異。
  • 其實設計模式就是這樣的,不要說同一種設計模式都有相似的地方,哪怕是不同的設計模式,它們的結構也大同小異,我們要做的,是將設計的原則精神掌握內化,而這些設計模式,只是一個工具,幫主你內化代碼設計精神的工具,舉個例子,具體A講的工廠模式和B說的工廠模式可能不一樣,這不重要,重要的是他們所講的工廠模式的精髓是一樣的。
  • 所以在你學習設計模式的時候,期望大家能夠自己進行演化,這樣更能方便大家,使大家更容易,更快速的內化掌握代碼設計精髓。
  • PS.部分類實現見文末

簡單工廠模式

  • 這是將類創建進行簡單封裝的模式,很容易就能夠想到,將需要的對象封裝在一個方法,通過參數判斷需要創建哪個類對象
/**
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:09
 **/
public class SimpleAeratedWaterFactory {

    public ColaAeratedWater getAeratedWater(String type){
        if("ColaOriginal".equals(type)){
            return new ColaOriginal();
        }else if("ColaBule".equals(type)){
            return new ColaBule();
        }else if("ColaDiet".equals(type)){
            return new ColaDiet();
        }else{
            throw new RuntimeException("沒有此類型可樂");
        }
    }
}
  • 調用也簡單,無需解釋
/**
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:09
 **/
public class SimpleFactoryMode {
    public static void main(String[] args) {
        SimpleAeratedWaterFactory factory = new SimpleAeratedWaterFactory();
        ColaAeratedWater water = factory.getAeratedWater("ColaOriginal");
        System.out.println(water.getName());

    }
}
  • 存在一個問題,如果要增加的新的可樂口味,我們不僅需要新增實現不同味道的可樂,而且還需要在工廠中添加if else代碼,據說這裏是違反ocp原則,是的,自己仔細想一想也是,工廠代碼被修改了

工廠方法模式

  • 我們將可樂的不同味道,實現在不同的類中,讓這個類去實現一個統一的創建可樂的工廠,即所謂網絡上流傳的將具體的實現延遲到子類中進行實現
/**
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:10
 **/
public interface ColaFactory {

    ColaAeratedWater createCola();
}
  • 藍色口味的可樂,實現可樂工廠ColaFactory實現其方法,返回藍色可樂對象
/**
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:10
 **/
public class BuleColaFactory implements ColaFactory {
    @Override
    public ColaAeratedWater createCola() {
        return new ColaBule();
    }
}

同理,無糖口味可樂的工廠

/**
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:10
 **/
public class DietColaFactory implements ColaFactory {
    @Override
    public ColaAeratedWater createCola() {
        return new ColaDiet();
    }
}
  • 在使用的時候,通過創建對應口味的可樂工廠,調用同樣的創建可樂方法
/**
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:08
 **/
public class FactoryMethodMode {

    public static void main(String[] args) {
        ColaFactory factory = new BuleColaFactory();
        ColaAeratedWater water = factory.createCola();
        System.out.println(water.getName());
    }

}
  • 簡單畫一下工廠方法模式的uml圖
    在這裏插入圖片描述

抽象工廠模式

  • 在工廠方法模式的基礎上進行擴展,比如要新增雪碧Sprite,工廠方法模式似乎就不能滿足設計模式原則的擴展需求了
  • 將藍色可樂工廠進一步抽象爲藍色汽水工廠,這樣不僅可以生產藍色可樂,也可以生產藍色雪碧(當然,我們目前沒有藍色雪碧,這種情況如何處理,我是有點木訥,是實現一個空方法還是在實現的方法裏拋出異常,又或是有更好的方法,希望看到此文的同學能告訴我)或其他藍色口味汽水
/**
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:11
 **/
public abstract class BuleAeratedWaterFactory implements AeratedWaterFactory {
    @Override
    public ColaAeratedWater createColaAeratedWater() {
        return new ColaBule();
    }

    @Override
    public SpriteAeratedWater createSpriteAeratedWater() {
        return null;
    }
}
  • 接下來是原味的汽水,可樂和雪碧都有,都得實現
/**
 *
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:11
 **/
public class OriginalAeratedWaterFactory implements AeratedWaterFactory{
    @Override
    public ColaAeratedWater createColaAeratedWater() {
        return new ColaOriginal();
    }

    @Override
    public SpriteAeratedWater createSpriteAeratedWater() {
        return new SpriteOriginal();
    }
}

抽象工廠,即可以生產可樂也可以生產雪碧,在擴展的時候,直接添加其他汽水飲料

/**
 * absFactory
 *
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:10
 **/
public interface AeratedWaterFactory {

      ColaAeratedWater createColaAeratedWater();

      SpriteAeratedWater createSpriteAeratedWater();

	  //增加其他汽水
	  //SodaAeratedWater createSodaAeratedWater();
}
  • 使用,創建不同口味的汽水工程,然後生產需要的汽水
/**
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:10
 **/
public class AbsFactoryMode {
    public static void main(String[] args) {
        AeratedWaterFactory originalAeratedWaterFactory = new OriginalAeratedWaterFactory();
        AeratedWater water = originalAeratedWaterFactory.createColaAeratedWater();
        System.out.println(water.getName());

    }
}

其他類

/**
 * 汽水
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:11
 **/
public interface AeratedWater {
    String getName();
}
/**
 * 工廠方法模式 
 * 使用的可樂父接口(也可以不要 用AeratedWater代替 個人認爲這些就是所謂的在學習過程中或初學時__不需要特別糾結的細節__ 在使用過程中遇到情況再隨機應變)
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:09
 **/
public interface ColaAeratedWater extends AeratedWater{
}
/**
 * 藍色可樂
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:09
 **/
public class ColaBule implements ColaAeratedWater {
    @Override
    public String getName() {
        return "ColaBule";
    }
}
/**
 * 原味可樂
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:09
 **/
public class ColaOriginal implements ColaAeratedWater {
    @Override
    public String getName() {
        return "ColaOriginal";
    }
}
/**
 * 雪碧
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:10
 **/
public interface SpriteAeratedWater extends AeratedWater{
}
/**
 * 原味雪碧
 * @program: ade-someproblem
 * @author: cade franklin
 * @create: 2019-12-21 21:11
 **/
public class SpriteOriginal implements SpriteAeratedWater {

    @Override
    public String getName() {
        return "SpriteOriginal";
    }
}

總結

  • 工廠模式的三種基本分支大概就是這樣了,個人感覺自己還是要理解其精神內涵,不要盲目的生搬硬套,不能鑽牛角尖,特別在當前博客氾濫相互借鑑質量不高的情況下,要有自己的理解,纔能有所提升。

願你不捨愛與自由。

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