Java設計模式——工廠模式

Java設計模式——工廠模式

工廠模式(Factory Pattern)屬於建立型模式,它提供了一種建立對象的最佳方式。html

在工廠模式中,咱們在建立對象時不會對客戶端暴露建立邏輯,而且是經過使用一個共同的接口來指向新建立的對象。術業有專攻就能很好的解釋工廠模式,工廠模式就是專業生產商,咱們拿來用就行了,不須要本身粗製亂遭,也不須要購買假冒僞劣產品,正規渠道拿貨,質量有保障,安全,放心。java

簡單工廠模式

簡單工廠模式不屬於23種設計模式。他是由一個工廠實例來建立咱們所須要的實例,適用於工廠類建立對象較少的場景。客戶端只須要傳入合適的參數就能獲取所需對象,不須要關心對象的建立邏輯。設計模式

代碼示例:安全

/**
 * @description: 水果產品接口
 * @author: lmc
 * @create: 2019-03-19 21:28
 **/

public interface IFruits {

    /**
     * 水果名稱
     */
    void getName();

    /**
     * 水果顏色
     */
    void getColor();

    /**
     * 水果味道
     */
    void getTaste();

}
/**
 * @description: 蘋果
 * @author: lmc
 * @create: 2019-03-19 21:33
 **/

public class Apple implements IFruits {

    @Override
    public void getName() {

        System.out.println(" 我是蘋果,水果的一種");
    }

    @Override
    public void getColor() {
        System.out.println(" 蘋果是紅色的");
    }

    @Override
    public void getTaste() {
        System.out.println(" 蘋果饞起來很甜很脆");
    }
}
/**
 * @description: 香蕉
 * @author: lmc
 * @create: 2019-03-19 21:33
 **/

public class Banana implements IFruits {

    @Override
    public void getName() {

        System.out.println(" 我是香蕉,水果的一種");
    }

    @Override
    public void getColor() {
        System.out.println(" 香蕉是黃色的");
    }

    @Override
    public void getTaste() {
        System.out.println(" 香蕉饞起來很甜很滑");
    }
}
/**
 * @description: 橙子
 * @author: lmc
 * @create: 2019-03-19 21:33
 **/

public class Orange implements IFruits {

    @Override
    public void getName() {

        System.out.println(" 我是橙子,水果的一種");
    }

    @Override
    public void getColor() {
        System.out.println(" 橙子是橙色的");
    }

    @Override
    public void getTaste() {
        System.out.println(" 橙子饞起來很甜水分足");
    }
}

上面的代碼 建立了一個水果接口,而且建立了三種水果分別實現了水果接口。app

/**
 * @description: 水果工廠
 * @author: lmc
 * @create: 2019-03-19 21:38
 **/

public class FruitsFactory {

    /**
     * @description: 
     * @param fruitsName
     * @return com.lmc.gp12380.pattern.factory.fruits.IFruits
     * @date 2019/5/23 15:44
     * @author lmc
     */
    public IFruits product(String fruitsName){

        if(null != fruitsName && fruitsName != ""){
            System.out.println("客戶需求的水果是"+fruitsName);
            if("蘋果".equals(fruitsName)){
                System.out.println("水果工廠生產了蘋果");
                return new Apple();
            }
            if("橙子".equals(fruitsName)){
                System.out.println("水果工廠生產了橙子");
                return new Orange();
            }
            if("香蕉".equals(fruitsName)){
                System.out.println("水果工廠生產了香蕉");
                return new Banana();
            }
            return null;
        }else{
            return null;
        }
    }
}

簡單工廠測試類ide

/**
 * @description: 水果工廠測試類
 * @author: lmc
 * @create: 2019-03-19 21:50
 **/

public class SimpleFactoryTest {

    public static void main(String[] args) {
        IFruits ifruits=null;
        FruitsFactory ifruitsFactory =new FruitsFactory();

        ifruits = ifruitsFactory.product("香蕉");
        getFruitsName(ifruits,"香蕉");

        ifruits = ifruitsFactory.product("蘋果");
        getFruitsName(ifruits,"蘋果");

        ifruits = ifruitsFactory.product("橙子");
        getFruitsName(ifruits,"橙子");

        ifruits = ifruitsFactory.product("草莓");
        getFruitsName(ifruits,"草莓");

    }

    public static void getFruitsName(IFruits ifruits,String ifruitsName){

        if(null != ifruits){
            ifruits.getName();
        }else{
            if(null == ifruitsName || ifruitsName==""){
                System.out.println("未指定水果讓水果工廠生產");
            }else{
                System.out.println("水果工廠暫時沒法生產"+ifruitsName);
            }

        }
    }
}

測試結果測試

客戶需求的水果是香蕉
水果工廠生產了香蕉
我是香蕉,水果的一種

客戶需求的水果是蘋果
水果工廠生產了蘋果
我是蘋果,水果的一種

客戶需求的水果是橙子
水果工廠生產了橙子
我是橙子,水果的一種

客戶需求的水果是草莓
水果工廠暫時沒法生產草莓

上面的代碼很簡單,客戶傳入不一樣的參數,就能獲取工廠對象可以生產的產品。業務需求中,工廠實例建立對象的業務邏輯每每是複雜的,運用簡單工廠模式,客戶端就不須要關心業務了,只要建立工廠對象,傳入參數調用就能獲取所需對象。ui

利:客戶端調用簡單,對於簡單的業務邏輯清晰明瞭。spa

弊:設計

  • 須要傳參,容易出錯。
    • 傳一個草莓參數,或者其餘亂七八糟的參數,就得不到所需對象,出問題了
  • 業務須要新的對象,須要更改工廠類,違背了開閉原則。
    • 就像上面那樣,我要一個草莓對象,工廠類暫時沒法建立,須要修改代碼。
  • 工廠類的職責太重,不利於擴展複雜的產品結構(產品族和產品等級結構的概念後面會有說到)。
    • 隨着要生產的對象愈來愈多,工廠類變成了萬能工廠了,違背了單一原則,不利於擴展和維護。

簡單工廠類圖:

工廠方法

工廠方法模式(FactoryMethodPattern)是指定義一個建立對象的接口(工廠接口),但讓實現這個 接口的類(工廠具體實現類)來決定實例化哪一個類,工廠方法讓類的實例化推遲到子類中進行。

現代化管理都是明確分工、專人幹專事、團隊協做。我們的程序代碼意思同樣的。

來一個水果工廠接口

/**
 * @description: 水果工廠接口
 * @author: lmc
 * @create: 2019-03-20 20:14
 **/

public interface IFruitsFactory {
    /**
     * 工廠的生產方法
     * @return IFruits
     */
    IFruits product();

}
/**
 * @description: 蘋果工廠
 * @author: lmc
 * @create: 2019-03-20 20:19
 **/

public class AppleFactory implements IFruitsFactory {
    @Override
    public IFruits product() {

        System.out.println("蘋果工廠只生產蘋果");
        return new Apple();
    }
}
/**
 * @description: 香蕉工廠
 * @author: lmc
 * @create: 2019-03-20 20:19
 **/

public class BananaFactory implements IFruitsFactory {
    @Override
    public IFruits product() {
        System.out.println("香蕉工廠只生產香蕉");
        return new Banana();
    }
}
/**
 * @description: 橙子工廠
 * @author: lmc
 * @create: 2019-03-20 20:19
 **/

public class OrangeFactory implements IFruitsFactory {
    @Override
    public IFruits product() {
        System.out.println("橙子工廠只生產橙子");
        return new Orange();
    }
}
/**
 * @description: 工廠方法測試
 * @author: lmc
 * @create: 2019-03-20 20:39
 **/

public class MethodFactoryTest {

    public static void main(String[] args) {

        IFruitsFactory iFruitsFactory= new AppleFactory();
        iFruitsFactory.product().getName();

        iFruitsFactory = new BananaFactory();
        iFruitsFactory.product().getName();

        iFruitsFactory = new OrangeFactory();
        iFruitsFactory.product().getName();
    }
}

運行結果:

蘋果工廠只生產蘋果
我是蘋果,水果的一種

香蕉工廠只生產香蕉
我是香蕉,水果的一種

橙子工廠只生產橙子
我是橙子,水果的一種

專人作專事,具體的對象只有具體的工廠建立。用戶只有選擇權,不須要傳入參數。對象的實例化推遲到了工廠實現類建立。

利:

  • 專人專事,遵循單一原則,子類工廠實現具體業務。讓業務更清晰
  • 遵循開閉原則,新增業務,只須要添加產品類和具體的產品工廠類就能夠了,增長產品擴展性。
    • 新增草莓產品,我只須要新增草莓類和草莓工廠就能夠了。

弊:

  • 類的個數容易過多,增長複雜度。
  • 增長了系統的抽象性和理解難度。

工廠方法模式類圖

抽象工廠模式

抽象工廠模式(Abstract Factory Pattern)是指提供一個建立一系列相關或相互依賴對象的接口,無須指定他們具體的類。客戶端(應用層)不依賴於產品類實例如何被建立、實現等細節,強調的是一系列相關的產品對象(屬於同一產品族)一塊兒使用建立對象須要大量重複的代碼。須要提供一個產品類的庫,全部的產品以一樣的接口出現,從而使客戶端不依賴於具體實現。

如今瞭解下上面提到的產品族和產品等級結構的概念。

產品族:屬於一個產品工廠的全部產品。

產品等級結構:不等產品工廠生產的相同的同類產品。

如今水果工廠需求再次升級,以前又一個水果接口 IFruits ,那麼咱們再增長 水果果乾接口IDriedFruits 、水果果汁接口 IJuice

/**
 * @description: 水果乾產品接口
 * @author: lmc
 * @create: 2019-03-19 21:28
 **/

public interface IDriedFruits {

    void getName();

    void getColor();

    void getTaste();

}
/**
 * @description: 水果果汁品接口
 * @author: lmc
 * @create: 2019-03-19 21:28
 **/

public interface IJuice {

    void getName();

    void getColor();

    void getTaste();

}

如今咱們有實現類 蘋果汁 AppleJuice 、 蘋果乾 DriedApple ......

/**
 * @description: 蘋果乾
 * @author: lmc
 * @create: 2019-03-19 21:33
 **/

public class DriedApple implements IDriedFruits {


    @Override
    public void getName() {

        System.out.println(" 我是蘋果乾,果乾的一種");
    }

    @Override
    public void getColor() {
        System.out.println(" 蘋果乾大概也是白色的吧");
    }

    @Override
    public void getTaste() {
        System.out.println(" 蘋果乾沒吃過,打個也是酸酸的吧");
    }
}
/**
 * @description: 蘋果汁
 * @author: lmc
 * @create: 2019-03-19 21:33
 **/

public class AppleJuice implements IJuice {


    @Override
    public void getName() {
        System.out.println(" 我是蘋果汁,果汁的一種");
    }

    @Override
    public void getColor() {
        System.out.println(" 蘋果汁大概是白色的吧");
    }

    @Override
    public void getTaste() {
        System.out.println(" 蘋果汁酸酸的");
    }
}
/**
 * @description: 香蕉幹
 * @author: lmc
 * @create: 2019-05-23 23:06
 **/

public class DriedBanana implements IDriedFruits {
    @Override
    public void getName() {
        System.out.println(" 我是香蕉幹,果乾的一種");
    }

    @Override
    public void getColor() {
        System.out.println(" 香蕉幹大概也是黃色的吧");
    }

    @Override
    public void getTaste() {
        System.out.println(" 香蕉幹甜甜的");
    }
}
/**
 * @description: 香蕉汁
 * @author: lmc
 * @create: 2019-05-23 23:10
 **/

public class BananaJuice implements IJuice {
    @Override
    public void getName() {
        System.out.println(" 我是香蕉汁,果汁的一種");
    }

    @Override
    public void getColor() {
        System.out.println(" 香蕉汁大概是白色的吧");
    }

    @Override
    public void getTaste() {
        System.out.println(" 香蕉汁甜甜的");
    }
}
/**
 * @description: 橙子幹
 * @author: lmc
 * @create: 2019-05-23 23:08
 **/

public class DriedOrange implements IDriedFruits{
    @Override
    public void getName() {
        System.out.println(" 我是橙子幹,果乾的一種");
    }

    @Override
    public void getColor() {
        System.out.println(" 橙子幹大概也是橙黃色的吧");
    }

    @Override
    public void getTaste() {
        System.out.println(" 香蕉乾沒吃過 應該是甜甜的");
    }
}
/**
 * @description: 橙汁
 * @author: lmc
 * @create: 2019-05-23 23:12
 **/

public class OrangeJuice implements IJuice {
    @Override
    public void getName() {
        System.out.println(" 我是橙汁,果汁的一種");
    }

    @Override
    public void getColor() {
        System.out.println(" 橙汁是橙色的吧");
    }

    @Override
    public void getTaste() {
        System.out.println(" 橙汁汁酸酸甜甜的");
    }
}

工廠類改造

抽象工廠接口,也能夠改爲抽象類

/**
 * @description: 抽象工廠
 * @author: lmc
 * @create: 2019-03-21 21:59
 **/

public interface IAbstractFruitsFactory {

    /**
     * @description: 水果生產
     * @return com.lmc.gp12380.pattern.factory.fruits.IFruits
     * @date 2019/5/24 8:33
     * @author lmc
     */
    IFruits productFruits();

    /**
     * @description: 果醬生產
     * @return com.lmc.gp12380.pattern.factory.fruits.IDriedFruits
     * @date 2019/5/24 8:34
     * @author lmc
     */
    IDriedFruits productIDriedFruits();

    /**
     * @description: 果汁生產
     * @return com.lmc.gp12380.pattern.factory.fruits.IJuice
     * @date 2019/5/24 8:34
     * @author lmc
     */
    IJuice productJuice();
}
/**
 * @description: 蘋果工廠
 * @author: lmc
 * @create: 2019-03-21 22:02
 **/

public class AppleFactory implements IAbstractFruitsFactory {

    /**
     * @description:蘋果生成
     * @return com.lmc.gp12380.pattern.factory.fruits.IFruits
     * @date 2019/5/23 15:14
     * @author lmc
     */
    @Override
    public IFruits productFruits() {
        return new Apple();
    }

    /**
     * @description: 蘋果醬生產
     * @return com.lmc.gp12380.pattern.factory.fruits.IDriedFruits
     * @date 2019/5/23 15:15
     * @author lmc
     */
    @Override
    public IDriedFruits productIDriedFruits() {
        return new DriedApple();
    }

    /**
     * @description: 蘋果汁生產
     * @return com.lmc.gp12380.pattern.factory.fruits.IJuice
     * @date 2019/5/23 15:15
     * @author lmc
     */
    @Override
    public IJuice productJuice() {
        return new AppleJuice();
    }
}
/**
 * @description: 香蕉工廠
 * @author: lmc
 * @create: 2019-05-24 08:35
 **/

public class BananaFactory implements IAbstractFruitsFactory {

    @Override
    public IFruits productFruits() {
        return new Banana();
    }

    @Override
    public IDriedFruits productIDriedFruits() {
        return new DriedBanana();
    }

    @Override
    public IJuice productJuice() {
        return new BananaJuice();
    }
}
/**
 * @description: 橙子工廠
 * @author: lmc
 * @create: 2019-05-24 08:27
 **/

public class OrangeFactory implements IAbstractFruitsFactory {
    @Override
    public IFruits productFruits() {
        return new Orange();
    }

    @Override
    public IDriedFruits productIDriedFruits() {
        return new DriedOrange();
    }

    @Override
    public IJuice productJuice() {
        return new OrangeJuice();
    }
}

抽象工廠實際上是一個產品族,具體的實現抽象工廠類生產的產品實例所產生同一產品類型,好比全部的水果是一個產品等級結構,全部的果醬也是一個產品等級結構,全部的果汁是一個產品等級結構。

/**
 * @description: 抽象工廠方法測試
 * @author: lmc
 * @create: 2019-03-20 20:39
 **/

public class AbstractFactoryTest {

    public static void main(String[] args) {

        AppleFactory appleFactory=new AppleFactory();
        IFruits apple= appleFactory.productFruits();
        apple.getName();
        apple.getColor();
        apple.getTaste();

        IDriedFruits appleDriedFruits=appleFactory.productIDriedFruits();
        appleDriedFruits.getColor();
        appleDriedFruits.getName();
        appleDriedFruits.getTaste();

        IJuice appleJuice=appleFactory.productJuice();
        appleJuice.getName();
        appleJuice.getColor();
        appleJuice.getTaste();

        System.out.println("_________________________________________");
        OrangeFactory orangeFactory=new OrangeFactory();
        IFruits orange= orangeFactory.productFruits();
        orange.getName();
        orange.getColor();
        orange.getTaste();

        IDriedFruits orangeDriedFruits=orangeFactory.productIDriedFruits();
        orangeDriedFruits.getColor();
        orangeDriedFruits.getName();
        orangeDriedFruits.getTaste();

        IJuice orangeJuice=orangeFactory.productJuice();
        orangeJuice.getName();
        orangeJuice.getColor();
        orangeJuice.getTaste();

        System.out.println("_________________________________________");
        BananaFactory bananaFactory=new BananaFactory();
        IFruits banana= bananaFactory.productFruits();
        banana.getName();
        banana.getColor();
        banana.getTaste();

        IDriedFruits bananaDriedFruits=bananaFactory.productIDriedFruits();
        bananaDriedFruits.getColor();
        bananaDriedFruits.getName();
        bananaDriedFruits.getTaste();

        IJuice bananaJuice=appleFactory.productJuice();
        bananaJuice.getName();
        bananaJuice.getColor();
        bananaJuice.getTaste();

    }
}

測試結構

我是蘋果,水果的一種
 蘋果乾大概也是白色的吧
 我是蘋果乾,果乾的一種
 蘋果乾沒吃過,打個也是酸酸的吧
 我是蘋果汁,果汁的一種
 蘋果汁大概是白色的吧
 蘋果汁酸酸的
_________________________________________
 我是橙子,水果的一種
 橙子幹大概也是橙黃色的吧
 我是橙子幹,果乾的一種
 橙子乾沒吃過 應該是酸酸甜甜的
 我是橙汁,果汁的一種
 橙汁是橙色的吧
 橙汁汁酸酸甜甜的
_________________________________________
 我是香蕉,水果的一種
 香蕉是黃色的
 香蕉饞起來很甜很滑
 香蕉幹大概也是黃色的吧
 我是香蕉幹,果乾的一種
 香蕉幹甜甜的
 我是香蕉汁,果汁的一種
 香蕉汁大概是白色的吧
 香蕉汁甜甜的

抽象工廠利弊

利:

  • 適合複雜業務需求,清晰描述複雜關係。
  • 專職專事,子類實現具體產品族業務。

弊:

  • 違背開閉原則,新增產品族或者產品等級須要修改代碼(產品迭代升級是有周期的)
  • 增長系統的抽象性和理解難度。

抽象工廠類圖

總結

工廠模式是一種面向對象程序封裝,屬於設計模式的建立型模式。客戶端或者調用者須要的對象由工廠建立,不須要知道建立對象複雜的業務邏輯。簡單工廠模式到工廠方法模式,再到抽象工廠模式。實際上是一種社會進步的表現。

簡單工廠就是一個小做坊,只要是工廠有這種產品均可以去生產。這就形成了管理不規範,維護困難。註定的簡單工廠就是簡單工廠,發展壯大不起來。當是呢方便,就比如你須要一箱牛奶,你去小超市就能夠拿了,確定不須要費九牛二虎之力去大草原找牛去擠奶吧。

工廠方法模式對應流水線生產企業。他們的產品比較少,管理規範,維護簡單。這樣的公司可以作大,出名,就好像那些只作單一產品的企業,好比服裝工廠,塑料工廠。可是呢,產品單一,面臨的競爭壓力大,面臨更復雜的業務一籌莫展,很容易被別人取而代之。對於新的產品,就要新建工程,新增流水線,投入成本過高。

抽象工廠模式:對應現代化產業鏈代工廠,生產、管理規範。強調的是產業鏈,一系列相互關聯的產品。造成了一個產品生態。讓用戶不可或缺,絕對是世界級的大企業,好比華爲,以及一些世界500強公司。他面臨的是一個產業鏈的生產管理。抽象工廠模式封裝的是複雜的產品關係業務。

原文出處:https://www.cnblogs.com/programmerkaixin/p/10918844.html

相關文章
相關標籤/搜索