工廠模式——看這一篇就夠了

最近根據(jù)公司的業(yè)務(wù)需要,封裝了一些平時(shí)開發(fā)中基本都會(huì)用到的基礎(chǔ)業(yè)務(wù)模塊,其中用的最多的就是各個(gè)工廠模式了存淫,同時(shí)也趁著這個(gè)機(jī)會(huì)復(fù)習(xí)了一下工廠模式。這篇文章會(huì)詳細(xì)介紹一下各個(gè)工廠模式的優(yōu)缺點(diǎn)沼填,如果你能完全理解了以下三個(gè)實(shí)例那么工廠模式就不在話下了桅咆。由于業(yè)務(wù)代碼不能公開,文中用到的實(shí)例會(huì)使用其他例子代替坞笙。
  我們知道Java里邊共有23種設(shè)計(jì)模式而工廠模式就有三種岩饼,它們分別是簡單工廠模式(并不在23中模式之中),工廠方法模式以及抽象工廠模式薛夜,其中我們通常所說的工廠模式指的是工廠方法模式籍茧,工廠方法模式是日常開發(fā)中使用頻率最高的一種設(shè)計(jì)模式,甚至在Android的源碼中也是隨處可見却邓。
  下面按照學(xué)習(xí)的難易程度由淺入深的來說說這三種模式硕糊,每種模式都會(huì)先從定義,使用場景腊徙,實(shí)例三方面入手简十。很多小伙伴都說學(xué)習(xí)的時(shí)候感覺理解了,實(shí)例也能看得懂撬腾,可在實(shí)際開發(fā)中就不會(huì)運(yùn)用了螟蝙,這因?yàn)闆]有記住它的使用場景,各位小伙伴一定要結(jié)合實(shí)例記住使用場景民傻,這樣才能在開發(fā)中達(dá)到融匯貫通的效果胰默。這也說明了設(shè)計(jì)模式只是思想场斑,沒有固定的代碼!
首先來看最簡單的牵署。

簡單工廠模式

簡單工廠模式其實(shí)并不算是一種設(shè)計(jì)模式漏隐,更多的時(shí)候是一種編程習(xí)慣。

定義:
  定義一個(gè)工廠類奴迅,根據(jù)傳入的參數(shù)不同返回不同的實(shí)例青责,被創(chuàng)建的實(shí)例具有共同的父類或接口。

適用場景:
  其實(shí)由定義也大概能推測出其使用場景取具,首先由于只有一個(gè)工廠類脖隶,所以工廠類中創(chuàng)建的對(duì)象不能太多,否則工廠類的業(yè)務(wù)邏輯就太復(fù)雜了暇检,其次由于工廠類封裝了對(duì)象的創(chuàng)建過程产阱,所以客戶端應(yīng)該不關(guān)心對(duì)象的創(chuàng)建】槠停總結(jié)一下適用場景:
 」沟拧(1)需要?jiǎng)?chuàng)建的對(duì)象較少。
 ≌ズ酢(2)客戶端不關(guān)心對(duì)象的創(chuàng)建過程怎燥。
以上就是簡單工廠模式簡單工廠模式的適用場景瘫筐,下面看一個(gè)具體的實(shí)例蜜暑。

實(shí)例:
  創(chuàng)建一個(gè)可以繪制不同形狀的繪圖工具,可以繪制圓形策肝,正方形肛捍,三角形,每個(gè)圖形都會(huì)有一個(gè)draw()方法用于繪圖之众,不看代碼先考慮一下如何通過該模式設(shè)計(jì)完成此功能拙毫。

由題可知圓形,正方形棺禾,三角形都屬于一種圖形缀蹄,并且都具有draw方法,所以首先可以定義一個(gè)接口或者抽象類膘婶,作為這三個(gè)圖像的公共父類缺前,并在其中聲明一個(gè)公共的draw方法。

public interface Shape {
    void draw();
}

這里定義成抽象類也是可以的悬襟,只不過接口是更高一級(jí)的抽象衅码,所以習(xí)慣定義成接口,而且接口支持多實(shí)現(xiàn)脊岳,方便以后擴(kuò)展逝段。

下面就是編寫具體的圖形垛玻,每種圖形都實(shí)現(xiàn)Shape 接口
圓形

public class CircleShape implements Shape {

    public CircleShape() {
        System.out.println(  "CircleShape: created");
    }

    @Override
    public void draw() {
        System.out.println(  "draw: CircleShape");
    }

}

正方形

public class RectShape implements Shape {
    public RectShape() {
       System.out.println(  "RectShape: created");
    }

    @Override
    public void draw() {
       System.out.println(  "draw: RectShape");
    }

}

三角形

public class TriangleShape implements Shape {

    public TriangleShape() {
        System.out.println(  "TriangleShape: created");
    }

    @Override
    public void draw() {
        System.out.println(  "draw: TriangleShape");
    }

}

下面是工廠類的具體實(shí)現(xiàn)

 public class ShapeFactory {
          public static final String TAG = "ShapeFactory";
          public static Shape getShape(String type) {
              Shape shape = null;
              if (type.equalsIgnoreCase("circle")) {
                  shape = new CircleShape();
              } else if (type.equalsIgnoreCase("rect")) {
                  shape = new RectShape();
              } else if (type.equalsIgnoreCase("triangle")) {
                  shape = new TriangleShape();
              }
              return shape;
          }
   }

在這個(gè)工廠類中通過傳入不同的type可以new不同的形狀,返回結(jié)果為Shape 類型奶躯,這個(gè)就是簡單工廠核心的地方了帚桩。
客戶端使用

畫圓形

    Shape shape= ShapeFactory.getShape("circle");
    shape.draw();

畫正方形

    Shape shape= ShapeFactory.getShape("rect");
    shape.draw();

畫三角形

    Shape shape= ShapeFactory.getShape("triangle");
    shape.draw();

只通過給ShapeFactory傳入不同的參數(shù)就實(shí)現(xiàn)了各種形狀的繪制。以上就是簡單工廠方式嘹黔,小伙伴們看明白了嗎朗儒?

工廠方法模式

工廠方法模式是簡單工廠的進(jìn)一步深化, 在工廠方法模式中参淹,我們不再提供一個(gè)統(tǒng)一的工廠類來創(chuàng)建所有的對(duì)象醉锄,而是針對(duì)不同的對(duì)象提供不同的工廠。也就是說每個(gè)對(duì)象都有一個(gè)與之對(duì)應(yīng)的工廠浙值。

定義:
  定義一個(gè)用于創(chuàng)建對(duì)象的接口恳不,讓子類決定將哪一個(gè)類實(shí)例化。工廠方法模式讓一個(gè)類的實(shí)例化延遲到其子類开呐。
  這次我們先用實(shí)例詳細(xì)解釋一下這個(gè)定義烟勋,最后在總結(jié)它的使用場景。

實(shí)例:
  現(xiàn)在需要設(shè)計(jì)一個(gè)這樣的圖片加載類筐付,它具有多個(gè)圖片加載器卵惦,用來加載jpg,png瓦戚,gif格式的圖片沮尿,每個(gè)加載器都有一個(gè)read()方法,用于讀取圖片较解。下面我們完成這個(gè)圖片加載類畜疾。

首先完成圖片加載器的設(shè)計(jì),編寫一個(gè)加載器的公共接口印衔。

public interface Reader {
    void read();
}

Reader 里面只有一個(gè)read()方法啡捶,然后完成各個(gè)圖片加載器的代碼。

Jpg圖片加載器

public class JpgReader implements Reader {
    @Override
    public void read() {
        System.out.print("read jpg");
    }
}

Png圖片加載器

public class PngReader implements Reader {
    @Override
    public void read() {
        System.out.print("read png");
    }
}

Gif圖片加載器

public class GifReader implements Reader {
    @Override
    public void read() {
        System.out.print("read gif");
    }
}

現(xiàn)在我們按照定義所說定義一個(gè)抽象的工廠接口ReaderFactory

public interface ReaderFactory {
    Reader getReader();
}

里面有一個(gè)getReader()方法返回我們的Reader 類奸焙,接下來我們把上面定義好的每個(gè)圖片加載器都提供一個(gè)工廠類瞎暑,這些工廠類實(shí)現(xiàn)了ReaderFactory 。

Jpg加載器工廠

public class JpgReaderFactory implements ReaderFactory {
    @Override
    public Reader getReader() {
        return new JpgReader();
    }
}

Png加載器工廠

public class PngReaderFactory implements ReaderFactory {
    @Override
    public Reader getReader() {
        return new PngReader();
    }
}

Gif加載器工廠

public class GifReaderFactory implements ReaderFactory {
    @Override
    public Reader getReader() {
        return new GifReader();
    }
}

在每個(gè)工廠類中我們都通過復(fù)寫的getReader()方法返回各自的圖片加載器對(duì)象与帆。

客戶端使用

讀取Jpg

ReaderFactory factory=new JpgReaderFactory();
Reader  reader=factory.getReader();
reader.read();

讀取Png

ReaderFactory factory=new PngReaderFactory();
Reader  reader=factory.getReader();
reader.read();

讀取Gif

ReaderFactory factory=new GifReaderFactory();
Reader  reader=factory.getReader();
reader.read();

可以看到上面三段代碼了赌,分別讀取了不同格式的圖片,不同之處在于針對(duì)不同的圖片格式聲明了不同的工廠鲤桥,進(jìn)而創(chuàng)建了相應(yīng)的圖片加載器揍拆。

通過這個(gè)實(shí)例各位小伙伴是不是對(duì)工廠模式有了進(jìn)一步的理解呢,和簡單工廠對(duì)比一下茶凳,最根本的區(qū)別在于簡單工廠只有一個(gè)統(tǒng)一的工廠類嫂拴,而工廠方法是針對(duì)每個(gè)要?jiǎng)?chuàng)建的對(duì)象都會(huì)提供一個(gè)工廠類播揪,這些工廠類都實(shí)現(xiàn)了一個(gè)工廠基類(本例中的ReaderFactory )。下面總結(jié)一下工廠方法的適用場景筒狠。

適用場景:

(1)客戶端不需要知道它所創(chuàng)建的對(duì)象的類猪狈。例子中我們不知道每個(gè)圖片加載器具體叫什么名,只知道創(chuàng)建它的工廠名就完成了床架過程辩恼。
 」兔怼(2)客戶端可以通過子類來指定創(chuàng)建對(duì)應(yīng)的對(duì)象。
以上場景使用于采用工廠方法模式灶伊。

抽象工廠模式

這個(gè)模式最不好理解疆前,而且在實(shí)際應(yīng)用中局限性也蠻大的,因?yàn)檫@個(gè)模式并不符合開閉原則聘萨。實(shí)際開發(fā)還需要做好權(quán)衡竹椒。
  抽象工廠模式是工廠方法的進(jìn)一步深化,在這個(gè)模式中的工廠類不單單可以創(chuàng)建一個(gè)對(duì)象米辐,而是可以創(chuàng)建一組對(duì)象胸完。這是和工廠方法最大的不同點(diǎn)。

定義:
  提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口翘贮,而無須指定它們具體的類赊窥。( 在抽象工廠模式中,每一個(gè)具體工廠都提供了多個(gè)工廠方法用于產(chǎn)生多種不同類型的對(duì)象)
  
抽象工廠和工廠方法一樣可以劃分為4大部分:
AbstractFactory(抽象工廠)聲明了一組用于創(chuàng)建對(duì)象的方法狸页,注意是一組锨能。
ConcreteFactory(具體工廠):它實(shí)現(xiàn)了在抽象工廠中聲明的創(chuàng)建對(duì)象的方法,生成一組具體對(duì)象肴捉。
AbstractProduct(抽象產(chǎn)品):它為每種對(duì)象聲明接口腹侣,在其中聲明了對(duì)象所具有的業(yè)務(wù)方法叔收。
ConcreteProduct(具體產(chǎn)品):它定義具體工廠生產(chǎn)的具體對(duì)象齿穗。
下面還是先看一個(gè)具體實(shí)例。

實(shí)例:
  現(xiàn)在需要做一款跨平臺(tái)的游戲饺律,需要兼容Android窃页,Ios,Wp三個(gè)移動(dòng)操作系統(tǒng)复濒,該游戲針對(duì)每個(gè)系統(tǒng)都設(shè)計(jì)了一套操作控制器(OperationController)和界面控制器(UIController)脖卖,下面通過抽閑工廠方式完成這款游戲的架構(gòu)設(shè)計(jì)。

由題可知巧颈,游戲里邊的各個(gè)平臺(tái)的UIController和OperationController應(yīng)該是我們最終生產(chǎn)的具體產(chǎn)品畦木。所以新建兩個(gè)抽象產(chǎn)品接口。

抽象操作控制器

public interface OperationController {
    void control();
}

抽象界面控制器

public interface UIController {
    void display();
}

然后完成各個(gè)系統(tǒng)平臺(tái)的具體操作控制器和界面控制器
Android

public class AndroidOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("AndroidOperationController");
    }
}

public class AndroidUIController implements UIController {
    @Override
    public void display() {
        System.out.println("AndroidInterfaceController");
    }
}

Ios

public class IosOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("IosOperationController");
    }
}

public class IosUIController implements UIController {
    @Override
    public void display() {
        System.out.println("IosInterfaceController");
    }
}

Wp

public class WpOperationController implements OperationController {
    @Override
    public void control() {
        System.out.println("WpOperationController");
    }
}
public class WpUIController implements UIController {
    @Override
    public void display() {
        System.out.println("WpInterfaceController");
    }
}

下面定義一個(gè)抽閑工廠砸泛,該工廠需要可以創(chuàng)建OperationController和UIController

public interface SystemFactory {
    public OperationController createOperationController();
    public UIController createInterfaceController();
}

在各平臺(tái)具體的工廠類中完成操作控制器和界面控制器的創(chuàng)建過程

Android

public class AndroidFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new AndroidOperationController();
    }

    @Override
    public UIController createInterfaceController() {
        return new AndroidUIController();
    }
}

Ios

public class IosFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new IosOperationController();
    }

    @Override
    public UIController createInterfaceController() {
        return new IosUIController();
    }
}

Wp

public class WpFactory implements SystemFactory {
    @Override
    public OperationController createOperationController() {
        return new WpOperationController();
    }

    @Override
    public UIController createInterfaceController() {
        return new WpUIController();
    }
}

客戶端調(diào)用:

    SystemFactory mFactory;
    UIController interfaceController;
    OperationController operationController;

    //Android
    mFactory=new AndroidFactory();
    //Ios
    mFactory=new IosFactory();
    //Wp
    mFactory=new WpFactory();

    interfaceController=mFactory.createInterfaceController();
    operationController=mFactory.createOperationController();
    interfaceController.display();
    operationController.control();

針對(duì)不同平臺(tái)只通過創(chuàng)建不同的工廠對(duì)象就完成了操作和UI控制器的創(chuàng)建十籍。小伙伴們可以對(duì)比一下蛆封,如果這個(gè)游戲使用工廠方法模式搭建需要?jiǎng)?chuàng)建多少個(gè)工廠類呢?下面總結(jié)一下抽象工廠的適用場景勾栗。

適用場景:
(1)和工廠方法一樣客戶端不需要知道它所創(chuàng)建的對(duì)象的類惨篱。
(2)需要一組對(duì)象共同完成某種功能時(shí)。并且可能存在多組對(duì)象完成不同功能的情況围俘。
(3)系統(tǒng)結(jié)構(gòu)穩(wěn)定砸讳,不會(huì)頻繁的增加對(duì)象。(因?yàn)橐坏┰黾泳托枰薷脑写a界牡,不符合開閉原則)

以上就是三種工廠模式的總結(jié)簿寂,如有不對(duì)之處還希望各位留言指正,以免誤導(dǎo)他人宿亡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陶耍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子她混,更是在濱河造成了極大的恐慌烈钞,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坤按,死亡現(xiàn)場離奇詭異毯欣,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)臭脓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門酗钞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人来累,你說我怎么就攤上這事砚作。” “怎么了嘹锁?”我有些...
    開封第一講書人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵葫录,是天一觀的道長。 經(jīng)常有香客問我领猾,道長米同,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任摔竿,我火速辦了婚禮面粮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘继低。我一直安慰自己熬苍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開白布袁翁。 她就那樣靜靜地躺著柴底,像睡著了一般钱磅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上似枕,一...
    開封第一講書人閱讀 51,215評(píng)論 1 299
  • 那天盖淡,我揣著相機(jī)與錄音,去河邊找鬼凿歼。 笑死褪迟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的答憔。 我是一名探鬼主播味赃,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼虐拓!你這毒婦竟也來了心俗?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤蓉驹,失蹤者是張志新(化名)和其女友劉穎城榛,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體态兴,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡狠持,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瞻润。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喘垂。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖绍撞,靈堂內(nèi)的尸體忽然破棺而出正勒,到底是詐尸還是另有隱情,我是刑警寧澤傻铣,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布章贞,位于F島的核電站,受9級(jí)特大地震影響矾柜,放射性物質(zhì)發(fā)生泄漏阱驾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一怪蔑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧丧荐,春花似錦缆瓣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽隧甚。三九已至,卻和暖如春渡冻,著一層夾襖步出監(jiān)牢的瞬間戚扳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來泰國打工族吻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帽借,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓超歌,卻偏偏與公主長得像砍艾,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子巍举,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理脆荷,服務(wù)發(fā)現(xiàn),斷路器懊悯,智...
    卡卡羅2017閱讀 134,652評(píng)論 18 139
  • 設(shè)計(jì)模式匯總 一蜓谋、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 3,939評(píng)論 1 15
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,085評(píng)論 25 707
  • 你是愿意做流星炭分? ????還是愿意做蠟燭孤澎? ????流星的光芒雖短暫,可是那種無比的輝煌和美麗欠窒,又豈是千萬根蠟燭所...
    leobert閱讀 428評(píng)論 0 0
  • 三石弟弟
    nomorenomorenev閱讀 361評(píng)論 0 0