作者:湯圓

個(gè)人博客:javalover.cc

前言

工廠我們都知道,就是生產(chǎn)東西的地方;

以前的農(nóng)業(yè)時(shí)代,我們需要啥東西,都是自己做,比如椅子、桌子;

后來(lái)到了工業(yè)時(shí)代,我們需要啥東西,大部分都是工廠做,你只需要告訴工廠需要的東西。

其實(shí)軟件中的工廠設(shè)計(jì)模式,也是類似:不需要我們自己去創(chuàng)建對(duì)象,只需要告訴工廠類,需要啥對(duì)象,工廠類會(huì)幫你創(chuàng)建。

下面我們循序漸進(jìn)來(lái)介紹下工廠模式

目錄

  • 制作一種椅子
  • 制作多種椅子
  • 創(chuàng)建一個(gè)椅子工廠(簡(jiǎn)單工廠模式)
  • 創(chuàng)建多個(gè)椅子工廠(工廠方法模式)
  • 創(chuàng)建多個(gè)椅子工廠(抽象工廠模式)

正文

1. 制作一種椅子

這個(gè)是最簡(jiǎn)單的了,就是誰(shuí)需要,誰(shuí)就創(chuàng)建一個(gè),很方便;

package pattern.factory.nofactory;/** * 沒(méi)有工廠,直接創(chuàng)建椅子 */public class NoFactory {    public static void main(String[] args) {        Chair chair = new Chair();        chair.prepare();        chair.make();        chair.box();    }    static class Chair {        public String name = "小椅子";        public void prepare() {            System.out.println(name + "的原材料是:A,B,C");        }        public void make(){            System.out.println(name + "制作中");        }        public void box(){            System.out.println(name + "打包中");        }    }}

2. 制作多種椅子

過(guò)了幾天,小李覺(jué)得這種椅子不舒服,沒(méi)有靠背,于是又創(chuàng)建了帶靠背的椅子

package pattern.factory.nofactory;/** * 沒(méi)有工廠,直接創(chuàng)建椅子(多種椅子) */public class NoFactory2 {    public static void main(String[] args) {        Chair chair = new ChairA();        chair.prepare();        chair.make();        chair.box();        Chair chairB = new ChairB();        chairB.prepare();        chairB.make();        chairB.box();    }}abstract class Chair {    public String name;    public abstract void prepare();    public void make(){        System.out.println(name + "制作中");    }    public void box(){        System.out.println(name + "打包中");    }}class ChairA extends Chair {    public ChairA() {        this.name = "小椅子";    }    @Override    public void prepare() {        System.out.println(name + "的原材料是:A,B,C");    }}class ChairB extends Chair {    public ChairB() {        this.name = "靠背椅";    }    @Override    public void prepare() {        System.out.println(name + "的原材料是:A2,B2,C2");    }}

這樣看來(lái),好像問(wèn)題也不大;

可以是如果不止兩種,而是十幾種幾十種呢?

此時(shí)再一個(gè)個(gè)創(chuàng)建就很麻煩了;

于是就有了工廠模式。

其實(shí)不止類型的增加需要工廠,數(shù)量的增加同樣也需要工廠(流水線制作提高效率)

3. 創(chuàng)建一個(gè)椅子工廠(簡(jiǎn)單工廠模式)

簡(jiǎn)單工廠模式:定義一個(gè)工廠類,它可以根據(jù)參數(shù)的不同返回不同類的實(shí)例,被創(chuàng)建的實(shí)例通常都具有共同的父類

小李花錢建了一個(gè)工廠,專門做各種各樣的椅子,這樣他每天都可以換不同的椅子坐;

大概的流程就是小李需要什么椅子,就告訴工廠,工廠來(lái)做(不再需要自己做)。

package pattern.factory.simple1;public class SimpleFactory1 {    public static void main(String[] args) {        SimpleChairFactory simpleChairFactory = new SimpleChairFactory();        simpleChairFactory.order("小椅子");        simpleChairFactory.order("靠背椅");    }}class SimpleChairFactory {    public Chair chair;    public void order(String name){        if(name == "小椅子"){            chair = new ChairA();        }else if(name == "靠背椅"){            chair = new ChairB();        }else{            chair = null;        }        if(chair != null){            chair.prepare();            chair.make();            chair.box();        }else{            System.out.println("找不到對(duì)應(yīng)的椅子");        }    }}abstract class Chair {    public String name;    public abstract void prepare();    public void make(){        System.out.println(name + "制作中");    }    public void box(){        System.out.println(name + "打包中");    }}class ChairA extends Chair {    public ChairA() {        this.name = "小椅子";    }    @Override    public void prepare() {        System.out.println(name + "的原材料是:A,B,C");    }}class ChairB extends Chair {    public ChairB() {        this.name = "靠背椅";    }    @Override    public void prepare() {        System.out.println(name + "的原材料是:A2,B2,C2");    }}

上面這個(gè)就是簡(jiǎn)單工廠模式,通過(guò)把自己的需求告訴工廠,工廠去做出你想要的東西;

4. 創(chuàng)建多個(gè)椅子工廠(工廠方法模式)

工廠方法模式:定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定將哪一個(gè)類實(shí)例化。

上面的簡(jiǎn)單工廠模式,確實(shí)很簡(jiǎn)單,用起來(lái)也很方便;

但是有一個(gè)很大的缺點(diǎn),就是如果需要增加椅子的種類,那么就需要修改工廠類的源代碼;

這樣一來(lái)就違背了開(kāi)閉原則:對(duì)類的擴(kuò)展開(kāi)放,對(duì)類的修改關(guān)閉;

所以我們需要對(duì)其進(jìn)行改進(jìn),創(chuàng)建多個(gè)工廠子類,來(lái)實(shí)現(xiàn)不同的創(chuàng)建任務(wù)。

package pattern.factory.method;/** * 工廠方法模式:將工廠類抽象出來(lái),子類去實(shí)現(xiàn)對(duì)象的創(chuàng)建 */public class MethodFactory {    public static void main(String[] args) {        SmallChairFactory smallFactory = new SmallChairFactory();        smallFactory.order();        BackChairFactory backFactory = new BackChairFactory();        backFactory.order();    }}interface ChairFactory{    void order();}class SmallChairFactory implements ChairFactory{    public Chair chair;    public void order(){            chair = new ChairA();            chair.prepare();            chair.make();            chair.box();    }}class BackChairFactory implements ChairFactory{    public Chair chair;    public void order(){        chair = new ChairB();        chair.prepare();        chair.make();        chair.box();    }}abstract class Chair {    public String name;    public abstract void prepare();    public void make(){        System.out.println(name + "制作中");    }    public void box(){        System.out.println(name + "打包中");    }}class ChairA extends Chair {    public ChairA() {        this.name = "小椅子";    }    @Override    public void prepare() {        System.out.println(name + "的原材料是:A,B,C");    }}class ChairB extends Chair {    public ChairB() {        this.name = "靠背椅";    }    @Override    public void prepare() {        System.out.println(name + "的原材料是:A2,B2,C2");    }}

5. 創(chuàng)建多個(gè)椅子工廠(抽象工廠模式)

抽象工廠模式:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無(wú)須指定它們具體的類。

上面的工廠方法模式,雖然解決了簡(jiǎn)單工廠模式的問(wèn)題(不好擴(kuò)展,單個(gè)類任務(wù)繁重),但是它本身也是有缺點(diǎn)的;

就是工廠方法模式中,一個(gè)工廠子類只負(fù)責(zé)生產(chǎn)一種產(chǎn)品,所以后期增加產(chǎn)品時(shí),會(huì)導(dǎo)致工廠類過(guò)多;

這時(shí)就需要將產(chǎn)品進(jìn)行一個(gè)簡(jiǎn)單的分類(按特定的屬性分類,比如按材質(zhì)分類):比如木頭椅子,全都讓一個(gè)廠去做;塑料椅子,讓另一個(gè)廠去做。

然后每個(gè)材質(zhì)的椅子,內(nèi)部再按結(jié)構(gòu)分類(小椅子,靠背椅);

這個(gè)就是抽象工廠模式的核心:將產(chǎn)品進(jìn)行分類,然后分配到不同的工廠子類中。

下面這個(gè)例子是先按照材質(zhì)進(jìn)行大的分類,再按照結(jié)構(gòu)進(jìn)行小的分類:

package pattern.factory.abstract1;/** * 抽象工廠模式:將工廠類抽象出來(lái),再把產(chǎn)品分類,每個(gè)子工廠生產(chǎn)特定類型的產(chǎn)品 * * 是工廠方法模式的升級(jí)版,工廠方法模式是一個(gè)工廠只做一個(gè)產(chǎn)品,而抽象工廠模式是一個(gè)工廠做一類產(chǎn)品 */public class AbstractFactory {    public static void main(String[] args) {        // 木頭        WoodChairFactory woodChairFactory = new WoodChairFactory();        woodChairFactory.orderSmallChair();        woodChairFactory.orderBackChair();        // 塑料        PlasticChairFactory plasticChairFactory = new PlasticChairFactory();        plasticChairFactory.orderSmallChair();        plasticChairFactory.orderBackChair();    }}interface ChairFactory{    void orderSmallChair();    void orderBackChair();}// 木頭椅子 工廠class WoodChairFactory implements ChairFactory{    public WoodChair chair;    @Override    public void orderSmallChair() {        chair = new WoodSmallChair();        chair.prepare();        chair.make();        chair.box();    }    @Override    public void orderBackChair() {        chair = new WoodBackChair();        chair.prepare();        chair.make();        chair.box();    }}// 塑料椅子 工廠class PlasticChairFactory implements ChairFactory{    public PlasticChair chair;    @Override    public void orderSmallChair() {        chair = new PlasticSmallChair();        chair.prepare();        chair.make();        chair.box();    }    @Override    public void orderBackChair() {        chair = new PlasticBackChair();        chair.prepare();        chair.make();        chair.box();    }}abstract class Chair {    public String type; // 木頭/塑料    public String name; // 小椅子/靠背椅    public void prepare(){        System.out.println(type+name + "的制作步驟是:A,B,C");    }    public void make(){        System.out.println(type+name + "制作中");    }    public void box(){        System.out.println(type+name + "打包中");    }}// 木頭椅class WoodChair extends Chair {    public WoodChair() {        this.type = "木頭-";    }}class WoodSmallChair extends WoodChair{    public WoodSmallChair(){        this.name = "小椅子";    }}class WoodBackChair extends WoodChair{    public WoodBackChair(){        this.name = "靠背椅";    }}// 塑料椅class PlasticChair extends Chair {    public PlasticChair() {        this.type = "塑料-";    }}class PlasticSmallChair extends PlasticChair{    public PlasticSmallChair(){        this.name = "小椅子";    }}class PlasticBackChair extends PlasticChair{    public PlasticBackChair(){        this.name = "靠背椅";    }}

上面的這個(gè)抽象工廠模式的例子,雖然現(xiàn)在增加椅子的種類很方便了,只需要擴(kuò)展一個(gè)椅子的子類就可以(比如鐵的椅子,只需要?jiǎng)?chuàng)建 IronChair 繼承 Chair就可以了);

但是缺點(diǎn)也很明顯,細(xì)心的朋友可能發(fā)現(xiàn)了,就是如果想要增加其他結(jié)構(gòu)的椅子,比如躺椅,那么就需要先改動(dòng) 椅子工廠接口(增加躺椅的制作過(guò)程),再在每個(gè)實(shí)現(xiàn)工廠類中去實(shí)現(xiàn)。

總結(jié)

簡(jiǎn)單工廠模式,簡(jiǎn)單好用,缺點(diǎn)是不易擴(kuò)展,違反了開(kāi)閉原則;

工廠方法模式,可擴(kuò)展,但是工廠類過(guò)多,會(huì)導(dǎo)致代碼繁重;

抽象工廠模式,可擴(kuò)展,工廠類也不會(huì)很多,但是這里的擴(kuò)展只是種類層面的擴(kuò)展,如果是結(jié)構(gòu)層面的還是不易擴(kuò)展,也會(huì)違反開(kāi)閉原則。

這三種工廠模式都屬于創(chuàng)建者型模式。