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

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

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

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


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

二、抽象工廠模式目的

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

三、示例場景

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

注意事項:每個廠家都有可能隨時新增新的產(chǎn)品。

四、代碼實現(xiàn)及對比

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

IPad類定義(平板的抽象定義,此處用接口實現(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類定義(手機的抽象定義,此處用接口實現(xiàn))

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

XiaomiPhone類定義(具體手機產(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類定義(具體手機產(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);
    }
}

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

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

xiaomi工廠的定義(實現(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工廠的定義(實現(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.");
        /*使用抽象工廠模式來創(chuàng)建產(chǎn)品等級中的某類產(chǎn)品類對象*/

        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)建還可以配合工廠方法/簡單工廠模式來實現(xiàn),此處為了避免與工廠方法/簡單工廠模式產(chǎn)生混淆,在具體產(chǎn)品工廠定義中就直接使用new關(guān)鍵字來創(chuàng)建具體的產(chǎn)品類了。

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

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

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

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

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

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

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

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

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

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

抽象工廠UML類圖.png

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

(1)優(yōu)點

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

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

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


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

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

(2)缺點

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

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

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

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

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