設(shè)計模式之"工廠模式"

這是我設(shè)計模式系列的第一篇總結(jié)萨脑。
首先講一下為什么需要使用工廠設(shè)計模式沈堡?
我們平時正常開發(fā)編碼的時候創(chuàng)建對象有幾種方式:
1.直接new
2.使用Class類的newInstance方法
3.使用Constructor類的newInstance方法
4.使用clone
5.使用序列化
最常見的就是第一種new的方式罗岖。但是有的時候往往創(chuàng)建對象和使用對象在同一個類當(dāng)中风纠。這就導(dǎo)致了這個類的任務(wù)很繁重,并且職責(zé)不清晰。并且違反了"開閉原則"。所以我們就要把創(chuàng)建對象和使用對象兩個職責(zé)分離開,這樣我們就引入了“工廠”的概念迟隅。我們把創(chuàng)建對象的任務(wù)交給“工廠”來做,什么時候用就直接從工廠中拿励七。
我們常說的工廠設(shè)計模式有“簡單工廠模式”智袭、“工廠模式”、和“抽象工廠模式”掠抬。
工廠三兄弟我從簡單到復(fù)雜(簡單到抽象)進(jìn)行總結(jié)吼野。

一.簡單工廠模式

簡單工廠模式定義如下:

簡單工廠模式(Simple Factory Pattern):定義一個工廠類,它可以根據(jù)參數(shù)的不同返回不同類的實例两波,被創(chuàng)建的實例通常都具有共同的父類瞳步。因為在簡單工廠模式中用于創(chuàng)建實例的方法是靜態(tài)(static)方法闷哆,因此簡單工廠模式又被稱為靜態(tài)工廠方法(Static Factory Method)模式,它屬于類創(chuàng)建型模式谚攒。


我們圍繞著一個購買Nike和Adidas產(chǎn)品的例子實現(xiàn)接下來的三種工廠模式。
首先簡單工廠模式顧名思義他的結(jié)構(gòu)比較簡單氛堕,那么適用于需要的對象比較少并且簡單的情況下馏臭。

簡單工廠

1.Shoes 抽象產(chǎn)品接口:這個接口代表了所有工廠最終生產(chǎn)出具體類的父類。
2.NikeShoes讼稚、AdidasShoes 具體產(chǎn)品實現(xiàn)類:抽象產(chǎn)品接口的實現(xiàn)類括儒,這里包含了具體方法的實現(xiàn)、自己的構(gòu)造方法锐想、初始化一些信息等帮寻。
3.ShoesFactory 工廠方法類:整個當(dāng)中最核心的類。此類包含了選擇創(chuàng)建對象的邏輯赠摇。

//抽象產(chǎn)品接口
public interface Shoes {
     //共有方法
     void display();
}

//Nike商品
public class NikeShoes implements Shoes {
    @Override
    public void display() {
        System.out.println("耐克鞋~~~");
    }
}
//Adidas商品
public class AdidasShoes implements Shoes {
    @Override
    public void display() {
        System.out.println("阿迪達(dá)斯鞋~~~");
    }
}

//工廠
public class ShoesFactory {
    public static Shoes getShoes(String brand) {
        if (brand.equalsIgnoreCase("nike")) {
            return new NikeShoes();
        } else if (brand.equalsIgnoreCase("adidas")) {
            return new AdidasShoes();
        } else {
            return null;
        }

    }
}
//購買鞋子入口函數(shù)
public class BuyShoes {
    public static void main(String args[]) {
        Shoes shoes = ShoesFactory.getShoes("nike");
        shoes.display();
    }
}


//輸出 
-------------
//耐克鞋~~~

我們可以看到這個工廠類通過傳入的參數(shù)來選擇創(chuàng)建具體類型的對象并且返回固逗。

二.工廠方法模式

接下來是工廠三兄弟的老二——“工廠方法模式”。
這個老二又是怎樣的需求促使它誕生的呢藕帜?
我們回憶一下剛才的老三"簡單工廠模式"烫罩,它適用于創(chuàng)建的對象類型較少的情況下。但是它有一個致命的缺點就是工廠類中的任務(wù)太重了洽故,如果對象的類型較多贝攒,則需要寫很多的if... else...,如果某一個類型改變了时甚,就要回過頭來去修改工廠中的邏輯代碼隘弊,這樣很不方便。把簡單工廠稍微抽象一下荒适,就誕生了我們的工廠方法模式來解決這樣的問題梨熙。
工廠方法模式定義:

工廠方法模式(Factory Method Pattern):定義一個用于創(chuàng)建對象的接口,讓子類決定將哪一個類實例化刀诬。工廠方法模式讓一個類的實例化延遲到其子類串结。工廠方法模式又簡稱為工廠模式(Factory Pattern),又可稱作虛擬構(gòu)造器模式(Virtual Constructor Pattern)或多態(tài)工廠模式(Polymorphic Factory Pattern)舅列。工廠方法模式是一種類創(chuàng)建型模式肌割。


工廠方法模式

1.ShoesFactory 抽象工廠:有別于簡單工廠這里多了一個“抽象工廠”接口。接口中聲明了創(chuàng)建具體產(chǎn)品的方法帐要。返回值是抽象的產(chǎn)品接口類型把敞。
2.NikeShoesFactory、AdidasShoesFactory 具體工廠類:實現(xiàn)抽象工廠接口榨惠,并實現(xiàn)創(chuàng)建對象的方法奋早,各個不同的具體工廠生產(chǎn)自己的具體產(chǎn)品盛霎。
3.產(chǎn)品接口和實現(xiàn)類與簡單工廠幾乎相同。

package Factory;
//抽象商品接口
public interface Shoes {
     void display();
}

//Nike商品實現(xiàn)類
public class NikeShoes implements Shoes {
    @Override
    public void display() {
        System.out.println("耐克鞋~~~");
    }
}

//Adidas商品實現(xiàn)類
public class AdidasShoes implements Shoes {
    @Override
    public void display() {
        System.out.println("阿迪達(dá)斯鞋~~~");
    }
}

//抽象工廠
public interface ShoesFactory {
     Shoes getShoes();
}


//  Nike工廠
public class NikeShoesFactory implements ShoesFactory {

    @Override
    public Shoes getShoes() {
        return new NikeShoes();
    }
}

//  Adidas工廠
public class AdidasShoesFactory implements ShoesFactory {
    @Override
    public Shoes getShoes() {
        return new AdidasShoes();
    }
}

//購買函數(shù)
public class BuyShoes {
    public static void main(String args[]) {
        ShoesFactory nikeShoesFactory = new NikeShoesFactory();
        Shoes nikeShoes =  nikeShoesFactory.getShoes();
        nikeShoes.display();
        ShoesFactory adidasShoesFactory = new AdidasShoesFactory();
        Shoes adidasShoes =  adidasShoesFactory.getShoes();
        adidasShoes.display();
    }
}

//輸出
-----------
//耐克鞋~~~
//阿迪達(dá)斯鞋~~~

我們可以看到這種優(yōu)化后的模式具體的產(chǎn)品從相對應(yīng)的具體工廠生產(chǎn)耽装,如果有新的產(chǎn)品愤炸,就橫向增加新的工廠即可,刪除同理不會橫向縱向的影響代碼結(jié)構(gòu)规个,滿足的了"開閉原則"。
那么我們想想這樣的模式還存在什么弊端呢姓建?

三.抽象工廠

工廠三兄弟的老大诞仓,也是真正Gof23種設(shè)計模式之一的"抽象工廠"模式。
定義:

抽象工廠模式(Abstract Factory Pattern):提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口速兔,而無須指定它們具體的類墅拭。抽象工廠模式又稱為Kit模式,它是一種對象創(chuàng)建型模式涣狗。

假設(shè)現(xiàn)在對象類型變得復(fù)雜橫向縱向兩個緯度都要擴(kuò)展谍婉?如下圖所示。


升級后的需求

按照老二工廠方法模式的思想镀钓。定義一個抽象工廠接口屡萤,每一個具體商品會實現(xiàn)對應(yīng)的工廠類,那么就有了2*3=6種工廠類掸宛,如果在繼續(xù)擴(kuò)展工廠實現(xiàn)類會變得很多很繁雜死陆,所以為了解決這種問題,我們在工廠方法模式上再抽象一層概念唧瘾。

抽象工廠模式

這樣我們只需要兩個具體工廠就能生產(chǎn)6種產(chǎn)品了措译。

//抽象產(chǎn)品——鞋子
public interface Shoes {
     void displayShoes();
}

//抽象產(chǎn)品——褲子
public interface Pants {
    void displayPants();
}

//抽象產(chǎn)品——衣服
public interface Clothes {
    void displayClothes();
}

//具體產(chǎn)品——耐克鞋子
public class NikeShoes implements Shoes {
    @Override
    public void displayShoes() {
        System.out.println("耐克鞋~~~");
    }
}
//具體產(chǎn)品——耐克衣服
public class NikeClothes implements Clothes {
    @Override
    public void displayClothes() {
        System.out.println("耐克衣服~~~");

    }
}
//具體產(chǎn)品——耐克褲子
public class NikePants implements Pants {
    @Override
    public void displayPants() {
        System.out.println("耐克褲子~~~");

    }
}
//具體產(chǎn)品——阿迪鞋子
public class AdidasShoes implements Shoes {
    @Override
    public void displayShoes() {
        System.out.println("阿迪達(dá)斯鞋子~~~");

    }
}
//具體產(chǎn)品——阿迪衣服
public class AdidasClothes implements Clothes{
    @Override
    public void displayClothes() {
        System.out.println("阿迪達(dá)斯衣服~~~");
    }
}
//具體產(chǎn)品——阿迪褲子
public class AdidasPants implements Pants {
    @Override
    public void displayPants() {
        System.out.println("阿迪達(dá)斯褲子~~~");

    }
}

//抽象工廠
public interface AbstractFactory {
    Shoes getShoes();
    Clothes getClothes();
    Pants getPants();
}
//耐克工廠
public class NikeFactory implements AbstractFactory {
    @Override
    public Shoes getShoes() {
        return new NikeShoes();
    }

    @Override
    public Clothes getClothes() {
        return new NikeClothes();
    }

    @Override
    public Pants getPants() {
        return new NikePants();
    }
}
//阿迪工廠
public class AdidasFactory implements AbstractFactory {
    @Override
    public Shoes getShoes() {
        return new AdidasShoes();
    }

    @Override
    public Clothes getClothes() {
        return new AdidasClothes();
    }

    @Override
    public Pants getPants() {
        return new AdidasPants();
    }
}
public class Shopping {
    public static void main(String args[]) {
        AbstractFactory nikeFactory = new NikeFactory();//可通過配置文件獲得
        Shoes nikeShoes = nikeFactory.getShoes();
        nikeShoes.displayShoes();
        Clothes nikeClothes = nikeFactory.getClothes();
        nikeClothes.displayClothes();

        AbstractFactory adidasFatory = new AdidasFactory();
        Shoes adidasShoes = adidasFatory.getShoes();
        adidasShoes.displayShoes();
        Pants adidasPants = adidasFatory.getPants();
        adidasPants.displayPants();
    }
}
//輸出
-------------------
//耐克鞋~~~
//耐克衣服~~~
//阿迪達(dá)斯鞋子~~~
//阿迪達(dá)斯褲子~~~

例子雖然簡單,但是想要應(yīng)用實際用的好還是需要多加練習(xí)的饰序。越抽象的方法越難理解但應(yīng)用越廣泛领虹。抽象工廠方法也有缺點。它不適合架構(gòu)設(shè)計好后頻繁修改求豫,因為橫向縱向都擴(kuò)展了以后必然存在“牽一發(fā)而動全身”的影響塌衰。所以要想把設(shè)計模式應(yīng)用的巧妙靈活,真的是一門需要慢慢修煉的“內(nèi)功”

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蝠嘉,一起剝皮案震驚了整個濱河市最疆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚤告,老刑警劉巖努酸,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異杜恰,居然都是意外死亡获诈,警方通過查閱死者的電腦和手機(jī)仍源,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舔涎,“玉大人笼踩,你說我怎么就攤上這事⊥鱿樱” “怎么了嚎于?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長昼伴。 經(jīng)常有香客問我匾旭,道長镣屹,這世上最難降的妖魔是什么圃郊? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮女蜈,結(jié)果婚禮上持舆,老公的妹妹穿的比我還像新娘。我一直安慰自己伪窖,他們只是感情好逸寓,可當(dāng)我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著覆山,像睡著了一般竹伸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上簇宽,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天勋篓,我揣著相機(jī)與錄音,去河邊找鬼魏割。 笑死譬嚣,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的钞它。 我是一名探鬼主播拜银,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼遭垛!你這毒婦竟也來了尼桶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤锯仪,失蹤者是張志新(化名)和其女友劉穎疯汁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卵酪,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡幌蚊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年谤碳,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溢豆。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜒简,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出漩仙,到底是詐尸還是另有隱情搓茬,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布队他,位于F島的核電站卷仑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏麸折。R本人自食惡果不足惜锡凝,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望垢啼。 院中可真熱鬧窜锯,春花似錦、人聲如沸芭析。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽馁启。三九已至驾孔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惯疙,已是汗流浹背翠勉。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留螟碎,地道東北人眉菱。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像掉分,于是被迫代替她去往敵國和親俭缓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,435評論 2 359

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

  • 設(shè)計模式概述 在學(xué)習(xí)面向?qū)ο笃叽笤O(shè)計原則時需要注意以下幾點:a) 高內(nèi)聚酥郭、低耦合和單一職能的“沖突”實際上华坦,這兩者...
    彥幀閱讀 3,752評論 0 14
  • 工廠模式是最常用的一類創(chuàng)建型設(shè)計模式,之前一直以為工廠模式只是23中設(shè)計模式中的一種不从,重新了解才知道這個模式還要細(xì)...
    晨鳴code閱讀 1,277評論 0 6
  • 設(shè)計模式匯總 一惜姐、基礎(chǔ)知識 1. 設(shè)計模式概述 定義:設(shè)計模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 3,948評論 1 15
  • 在面向?qū)ο缶幊讨? 最通常的方法是一個new操作符產(chǎn)生一個對象實例,new操作符就是用來構(gòu)造對象實例的。但是在一些...
    聶叼叼閱讀 4,004評論 2 16
  • 1. 簡單工廠 簡單工廠模式又稱為靜態(tài)工廠模式歹袁,它屬于創(chuàng)建型模式坷衍。在簡單工廠模式中,可以根據(jù)不同的參數(shù)返回不同類的...
    落英墜露閱讀 220評論 0 1