03 設(shè)計(jì)模式自學(xué)筆記(Java)-抽象工廠模式Abstract Factory[創(chuàng)建型模式]

一、抽象工廠模式的本質(zhì)

抽象工廠模式封裝同一產(chǎn)品族(產(chǎn)品族可以認(rèn)為是相關(guān)的產(chǎn)品,如電腦和鼠標(biāo)鍵盤(pán)可稱為一個(gè)產(chǎn)品族)的創(chuàng)建細(xì)節(jié),工廠方法抽象了一個(gè)產(chǎn)品等級(jí)的創(chuàng)建細(xì)節(jié)(產(chǎn)品等級(jí)可以認(rèn)為是同類產(chǎn)品按照不同的指標(biāo)分成了不同的等級(jí),如電腦的低配版、高配版、旗艦版等),一個(gè)產(chǎn)品族里面有不同類的產(chǎn)品(如電子產(chǎn)品族里面有手機(jī)、電腦、平板等,其中電子產(chǎn)品可認(rèn)為是一個(gè)抽象的產(chǎn)品族,而手機(jī)、電腦、平板可認(rèn)為是不同的產(chǎn)品等級(jí)或者類,手機(jī)產(chǎn)品類中又有蘋(píng)果、華為、小米等),抽象工廠模式對(duì)產(chǎn)品族進(jìn)行了抽象,抽象工廠就是在產(chǎn)品族這一層進(jìn)行了抽象,也就是說(shuō)她能夠創(chuàng)建的產(chǎn)品種類更多。

抽象工廠模式的本質(zhì)是通過(guò)提供統(tǒng)一的接口,保證在同一工廠中創(chuàng)建產(chǎn)品族中的不同產(chǎn)品(產(chǎn)品類/產(chǎn)品等級(jí))。


抽象工廠模式的產(chǎn)品族和產(chǎn)品等級(jí).png

二、抽象工廠模式目的

抽象工廠模式的目的是通過(guò)抽象工廠創(chuàng)建一系列相關(guān)的產(chǎn)品類對(duì)象,而無(wú)需指定其具體產(chǎn)品類。如上圖所示,抽象工廠能夠創(chuàng)建小米手機(jī)類對(duì)象或者其它產(chǎn)品類對(duì)象,而不需要客戶端顯示的使用new關(guān)鍵字來(lái)創(chuàng)建相關(guān)產(chǎn)品類的對(duì)象。同時(shí),抽象工廠統(tǒng)一負(fù)責(zé)一個(gè)產(chǎn)品族中的不同產(chǎn)品等級(jí)的產(chǎn)品,這樣就實(shí)現(xiàn)了對(duì)創(chuàng)建產(chǎn)品類對(duì)象的統(tǒng)一封裝,也就是說(shuō),通過(guò)具體的抽象工廠類可以創(chuàng)建同一產(chǎn)品族中不同的產(chǎn)品等級(jí)的產(chǎn)品類對(duì)象。

三、示例場(chǎng)景

某個(gè)電腦公司的在線購(gòu)物網(wǎng)站可售賣不同廠家(如小米、華為、蘋(píng)果)的電腦、手機(jī)、平板等電子產(chǎn)品,網(wǎng)站需要為客戶提供各種電子的配置信息查看功能,每當(dāng)用戶想查看某個(gè)電子產(chǎn)品配置時(shí),需要給出該電子產(chǎn)品生產(chǎn)日期以及價(jià)格等信息。

注意事項(xiàng):每個(gè)廠家都有可能隨時(shí)新增新的產(chǎn)品。

四、代碼實(shí)現(xiàn)及對(duì)比

從上述示例場(chǎng)景中可以看出,每個(gè)廠家都會(huì)出售手機(jī)、電腦、平板,根據(jù)抽象工廠模式的設(shè)計(jì)思想,我們可以分別將手機(jī)、電腦和平板設(shè)置為產(chǎn)品等級(jí),將每個(gè)廠家的所有手機(jī)、電腦、平板設(shè)置為產(chǎn)品族,然后,通過(guò)抽象工廠統(tǒng)一提供統(tǒng)一產(chǎn)品族(廠家)中產(chǎn)品等級(jí)中的某個(gè)產(chǎn)品(如手機(jī))。

IPad類定義(平板的抽象定義,此處用接口實(shí)現(xiàn))

public interface IPad {
    void Drawing(String picName);
    void PlayingFilm(String filmName);
}

XiaomiPad類定義(具體平板產(chǎn)品類)

public class XiaomiPad implements IPad{

    @Override
    public void Drawing(String picName) {
        System.out.println("Drawing a picture with 小米 Pad: " + picName);
    }

    @Override
    public void PlayingFilm(String filmName) {
        System.out.println("Watching a file with 小米 Pad: " + filmName);
    }
}

HuaweiPad類定義(具體平板產(chǎn)品類)

public class HuaweiPad implements IPad{
    @Override
    public void Drawing(String picName) {
        System.out.println("Drawing a picture with 華為 Pad: " + picName);
    }

    @Override
    public void PlayingFilm(String filmName) {
        System.out.println("Watching a file with 華為 Pad: " + filmName);
    }
}

IPhone類定義(手機(jī)的抽象定義,此處用接口實(shí)現(xiàn))

public interface IPhone {
    void calling(String number);
    void sendMessage(String msg);
}

XiaomiPhone類定義(具體手機(jī)產(chǎn)品類)

public class XiaomiPhone implements IPhone{
    @Override
    public void calling(String num) {
        System.out.println("Make calls using your 小米 phone: "+num);
    }

    @Override
    public void sendMessage(String msg) {
        System.out.println("Send messages using your 小米 phone: "+msg);
    }
}

HuaweiPhone類定義(具體手機(jī)產(chǎn)品類)

public class HuaweiPhone implements IPhone{
    @Override
    public void calling(String num) {
        System.out.println("Make calls using your 華為 phone: "+ num);
    }

    @Override
    public void sendMessage(String msg) {
        System.out.println("Send messages using your 華為 phone: "+msg);
    }
}

抽象工廠的抽象類定義(此處用接口實(shí)現(xiàn))

public interface IAbstractFactory {
    IPad createPad();
    IPhone createPhone();
}

xiaomi工廠的定義(實(shí)現(xiàn)抽象工廠,提供產(chǎn)品族中各種產(chǎn)品的具體創(chuàng)建)

public class XiaomiFactory implements IAbstractFactory{
    @Override
    public IPad createPad() {
        return new XiaomiPad();
    }

    @Override
    public IPhone createPhone() {
        return new XiaomiPhone();
    }
}

Huawei工廠的定義(實(shí)現(xiàn)抽象工廠,提供產(chǎn)品族中各種產(chǎn)品的具體創(chuàng)建)

public class HuaweiFactory implements IAbstractFactory{
    @Override
    public IPad createPad() {
        return new HuaweiPad();
    }

    @Override
    public IPhone createPhone() {
        return new HuaweiPhone();
    }
}

客戶端類定義

public class main {
    public static void main(String[] args) {

        System.out.println("Abstract Factory Pattern: client.");
        /*使用抽象工廠模式來(lái)創(chuàng)建產(chǎn)品等級(jí)中的某類產(chǎn)品類對(duì)象*/

        IAbstractFactory xiaomiFactory = new XiaomiFactory();
        IPhone xiaomiPhone = xiaomiFactory.createIphone();
        xiaomiPhone.calling("1111111111111");
        xiaomiPhone.sendMessage("How are you?");
        IPad xiaomiPad = xiaomiFactory.createPad();
        xiaomiPad.PlayingFilm("Fast & Furious 9");
        xiaomiPad.Drawing("Mona Lisa");

        System.out.println("-----------------------------------------------------");

        IAbstractFactory huaweiFactory = new HuaweiFactory();
        IPhone huaweiPhone = huaweiFactory.createIphone();
        huaweiPhone.calling("222222222");
        huaweiPhone.sendMessage("Do you have a nice day?");
        IPad huaweiPad = huaweiFactory.createPad();
        huaweiPad.Drawing("The Last Supper");
        huaweiPad.PlayingFilm("流浪地球");
    }
}

注意:這里的具體的產(chǎn)品類的創(chuàng)建還可以配合工廠方法/簡(jiǎn)單工廠模式來(lái)實(shí)現(xiàn),此處為了避免與工廠方法/簡(jiǎn)單工廠模式產(chǎn)生混淆,在具體產(chǎn)品工廠定義中就直接使用new關(guān)鍵字來(lái)創(chuàng)建具體的產(chǎn)品類了。

五、抽象工廠模式的UML類圖

抽象工廠模式UML類關(guān)系圖.png

抽象工廠模式的關(guān)鍵類與相互的關(guān)系如上圖所示。

IPad和IPhone為抽象類,定義了具體產(chǎn)品類的屬性和方法;

HuaweiPad、XiaomiPad、HuaweiPhone、XiaomiPhone這四個(gè)類分別是上述兩個(gè)抽象類的具體實(shí)現(xiàn)類,實(shí)現(xiàn)抽象類中定義的方法,如手機(jī)的打電話方法、平板的看電影方法;

IAbstractFactory類為抽象工廠類,定義了具體產(chǎn)品工廠需要提供的產(chǎn)品類創(chuàng)建的方法,需要包含整個(gè)產(chǎn)品族中所有產(chǎn)品類的創(chuàng)建方法;

XiaomiFactory和HuaweiFactory這兩個(gè)類就是IAbstractFactory抽象類的具體實(shí)現(xiàn)類,分別實(shí)現(xiàn)了各自產(chǎn)品族中不同產(chǎn)品類的創(chuàng)建方法;

然后,客戶端類通過(guò)創(chuàng)建具體工廠類開(kāi)啟具體產(chǎn)品類實(shí)例的創(chuàng)建,具體產(chǎn)品類實(shí)例對(duì)象的創(chuàng)建過(guò)程如下:

第一步:創(chuàng)建抽象工廠的具體實(shí)現(xiàn)類實(shí)例,如 IAbstractFactory xiaomiFactory = new XiaomiFactory();,這時(shí)候,小米工廠就可以創(chuàng)建小米這個(gè)產(chǎn)品族中不同的產(chǎn)品了;

第二步:利用具體工廠創(chuàng)建具體產(chǎn)品類實(shí)例對(duì)象,如IPhone xiaomiPhone = xiaomiFactory.createIphone();具體產(chǎn)品創(chuàng)建完成。

抽象工廠UML類圖.png

六、抽象工廠模式的優(yōu)缺點(diǎn)

(1)優(yōu)點(diǎn)

  • 抽象工廠模式隔離了具體類的生產(chǎn),使得客戶并不需要了解具體產(chǎn)品如何被創(chuàng)建的。

  • 當(dāng)一個(gè)產(chǎn)品族中的多個(gè)對(duì)象被設(shè)計(jì)成一起工作時(shí),它能保證客戶端始終只使用同一個(gè)產(chǎn)品族中的對(duì)象。

  • 增加新的具體工廠和產(chǎn)品族很方便,無(wú)須修改已有系統(tǒng),符合“開(kāi)閉原則”。


    新增產(chǎn)品族時(shí),類圖變化.png

如上圖所示,當(dāng)需要新增產(chǎn)品族的時(shí)候,直接添加相關(guān)的具體產(chǎn)品類和工廠類即可。

(2)缺點(diǎn)

  • 增加新的產(chǎn)品等級(jí)結(jié)構(gòu)很復(fù)雜,需要修改抽象工廠和所有的具體工廠類,對(duì)“開(kāi)閉原則”的支持呈現(xiàn)傾斜性。
抽象工廠模式UML類關(guān)系圖-新增產(chǎn)品等級(jí).png

如上圖所示,當(dāng)需要新增產(chǎn)品時(shí),需要修改響應(yīng)的工廠類(抽象和具體工廠類都需要修改),違反“開(kāi)閉原則”。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容