java設計模式-抽象工廠模式

抽象工廠模式詳解

 一,概述

  抽象工廠模式爲一個產品家族提供了統一的建立接口。當須要這個產品家族的某一系列的時候,能夠從抽象工廠中選出相對應的系列來建立一個具體的工廠類別。這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。設計模式

  在抽象工廠模式中,接口是負責建立一個相關對象的工廠,不須要顯式指定它們的類。每一個生成的工廠都能按照工廠模式提供對象。iphone

  相關術語:ide

  • 產品等級結構:產品的繼承結構,與類的繼承類似。例如筆記本是一個抽象的類,那麼華爲筆記本、蘋果和聯想筆記本就是其子類。測試

  • 產品族:指同一個工廠生產的,位於不一樣的產品等級結構的一組產品。例如華爲筆記本、手機、路由器等都產自華爲,筆記本的等級結構不一樣,構成一個產品族。字體

  • 抽象工廠:是一個接口,抽象工廠模式的核心,包含對多個產品等級結構的聲明,任何工廠類都必須實現這個接口。spa

  • 具體工廠:是抽象工廠的實現,負責實例化某個產品族中的產品對象。例如華爲工廠生產華爲筆記本、手機、路由器等。

二,產品族和產品等級結構圖

  咱們以一個品牌爲一個產品族,電腦、手機、路由器爲產品等級,每個品牌都有本身的產品族,這就構成一個完整產品羣;設計

  橫向表明一族,縱向表明一個等級,橫縱交集表明某一個品牌的某一個產品(好比下圖中交集的點爲電腦),請看下圖;code

  

 三,UML圖

  這個類圖其實比較簡單,簡單說明下:router

  產品頂級接口:主要被產品抽象類實現;對象

  產品抽象類:某個具體產品要實現的類;

  具體實現類:具體產品實現,好比華爲路由器實現自抽象類AbstractRouter;

  工廠接口:工廠接口中定義建立每一個產品方法;

  具體華爲工廠:實現工廠接口,建立華爲一族產品(路由器、手機、電腦);

  

 四,具體代碼實現

  代碼中咱們以華爲產品爲例,分別定義華爲電腦、手機、路由器產品,從UML類圖中能夠看出咱們的產品結構層級比較清晰,如今咱們先設計咱們產品。

  下面開始定義產品;

  產品頂級接口;

package pattern.abstractfactory.product;
/**
 * 定義產品接口
 * @author ningbeibei
 */
public interface InterfaceProduct {
    void get();
}

  定義計算機抽象類並實現產品InterfaceProduct 接口;

package pattern.abstractfactory.product;
/**
 * 定義計算機產品抽象類,並實現產品接口InterfaceProduct
 * @author ningbeibei
 */
public abstract class AbstractComputers implements InterfaceProduct {
    public abstract void get();
}

  定義手機抽象類並實現產品InterfaceProduct 接口;

package pattern.abstractfactory.product;
/**
 * 定義手機抽象類,並實現產品接口InterfaceProduct
 * @author ningbeibei
 */
public abstract class AbstractPhone  implements InterfaceProduct {
    public abstract void get();
}

  定義路由器抽象類並實現產品InterfaceProduct 接口;

package pattern.abstractfactory.product;
/**
 * 定義路由器產品抽象類,並實現InterfaceProduct接口
 * @author ningbeibei
 */
public abstract class AbstractRouter implements InterfaceProduct{
    public abstract void get();
}

  定義華爲電腦具體實現類,繼承AbstractComputers抽象類;

package pattern.abstractfactory.product;
/**
  * 華爲電腦實現類
 * @author ningbeibei
 */
public class HuaWeiComputer extends AbstractComputers{
    @Override
    public void get() {
        System.out.println("華爲筆記本");
    }
}

  定義華爲手機具體實現類,繼承AbstractPhone抽象類;

package pattern.abstractfactory.product;
/**
  *  華爲手機實現類,
 * @author ningbeibei
 */
public class HuaWeiPhone extends AbstractPhone{
    @Override
    public void get() {
        System.out.println("華爲手機");
    }
}

  定義華爲路由器具體實現類,繼承AbstractRouter抽象類;

package pattern.abstractfactory.product;
/**
 * 華爲路由器
 * @author ningbeibei
 */
public class HuaWeiRouter extends AbstractRouter {
    @Override
    public void get() {
        System.out.println("華爲品牌路由器");
    }
}

  下面開始定義工廠;

  定義工廠接口;

package pattern.abstractfactory.factory;
import pattern.abstractfactory.product.InterfaceProduct;
/**
 * 定義產品工廠接口,
 * @author ningbeibei
 */
public interface InterfactFactory {
    //手機產品
    InterfaceProduct createPhone();
    //電腦產品
    InterfaceProduct createComputer();
    //路由器產品
    InterfaceProduct createRouter();
}

  具體工廠實現類,實現 InterfactFactory  接口;

package pattern.abstractfactory.factory;
import pattern.abstractfactory.product.HuaWeiComputer;
import pattern.abstractfactory.product.HuaWeiPhone;
import pattern.abstractfactory.product.HuaWeiRouter;
import pattern.abstractfactory.product.InterfaceProduct;
/**
 * 華爲工廠
 * @author ningbeibei
 */
public class HuaWeiFactory implements InterfactFactory {
    /**
     * 建立電腦對象並返回
     */
    @Override
    public InterfaceProduct createComputer() {
        return new HuaWeiComputer();
    }
    /**
     * 建立手機對象並返回
     */
    @Override
    public InterfaceProduct createPhone() {
        return new HuaWeiPhone();
    }
    /**
     * 建立路由器對象並返回
     */
    @Override
    public InterfaceProduct createRouter() {
        return new HuaWeiRouter();
    }
}

  測試類;

package pattern.abstractfactory;
import pattern.abstractfactory.factory.HuaWeiFactory;
import pattern.abstractfactory.factory.InterfactFactory;
import pattern.abstractfactory.product.InterfaceProduct;
/**
 * 抽象工廠模式測試類
 * @author ningbeibei
 */
public class test {
    public static void main(String[] args) {
        //建立華爲品牌工廠
        InterfactFactory huawei = new HuaWeiFactory();
        //經過華爲工廠獲取華爲電腦對象
        InterfaceProduct computer = huawei.createComputer();
        computer.get();
        //經過華爲工廠獲取華爲手機對象
        InterfaceProduct phone = huawei.createPhone();
        phone.get();
        //經過華爲工廠獲取華爲路由器對象
        InterfaceProduct router = huawei.createRouter();
        router.get();
    }
}

  運行結果;

五,抽象工廠方法模式如何擴展產品族

  抽象工廠模式對於橫向擴展方便,對於縱向擴展很是困難也就是說:假如咱們要擴展一個新的品牌,好比擴展一個小米品牌,小米產品有電腦、手機、路由器,擴展新品牌就是橫向擴展,很是方便,可是咱們要給小米添加一個電飯煲產品卻很是困難,這就是縱向擴展,因此在使用抽象工廠模式時必定要選擇合適的場景,也就是在不一樣場景中使用最適合的模式纔是設計模式的精髓。

  下面咱們就來橫向擴展一個新品牌的產品族,須要添加電腦、手機、路由器具體類(小米品牌)代碼以下;

  小米電腦

package pattern.abstractfactory.product;
/**
 * 小米電腦,繼承自 AbstractComputers 抽象類
 * @author ningbeibei
 */
public class MiComputer extends AbstractComputers {
    @Override
    public void get() {
        System.out.println("小米電腦");
    }
}

  小米手機

package pattern.abstractfactory.product;
/**
 * 小米手機,繼承自 AbstractPhone 抽象類
 * @author ningbeibei
 */
public class MiPhone extends AbstractPhone {
    @Override
    public void get() {
        System.out.println("小米手機");
    }
}

  小米路由器

package pattern.abstractfactory.product;
/**
  * 小米路由器,繼承自 AbstractRouter 抽象類
 * @author ningbeibei
 */
public class MiRouter extends AbstractRouter{
    @Override
    public void get() {
        System.out.println("小米路由器");
    }
}

  添加小米具體工廠類

package pattern.abstractfactory.factory;
import pattern.abstractfactory.product.InterfaceProduct;
import pattern.abstractfactory.product.MiComputer;
import pattern.abstractfactory.product.MiPhone;
import pattern.abstractfactory.product.MiRouter;
/**
 * 小米工廠,實現 InterfactFactory 接口
 * @author ningbeibei
 */
public class MiFactory implements InterfactFactory{
    //小米手機
    @Override
    public InterfaceProduct createPhone() {
        return new MiPhone();
    }
    //小米電腦
    @Override
    public InterfaceProduct createComputer() {
        return new MiComputer();
    }
    //小米路由器
    @Override
    public InterfaceProduct createRouter() {
        return new MiRouter();
    }
}

  最後編寫測試類,代碼中紅色字體爲新擴展的品牌產品

package pattern.abstractfactory;
import pattern.abstractfactory.factory.HuaWeiFactory;
import pattern.abstractfactory.factory.InterfactFactory;
import pattern.abstractfactory.factory.MiFactory;
import pattern.abstractfactory.product.InterfaceProduct;
/**
 * 抽象工廠模式測試類
 * @author ningbeibei
 */
public class test {
    public static void main(String[] args) {
        // 建立華爲品牌工廠
        InterfactFactory huawei = new HuaWeiFactory();
        // 經過華爲工廠獲取華爲電腦對象
        InterfaceProduct computer = huawei.createComputer();
        computer.get();
        // 經過華爲工廠獲取華爲手機對象
        InterfaceProduct phone = huawei.createPhone();
        phone.get();
        // 經過華爲工廠獲取華爲路由器對象
        InterfaceProduct router = huawei.createRouter();
        router.get();

        // 建立小米品牌工廠
        InterfactFactory Mifactory = new MiFactory();
        // 經過小米工廠獲取小米電腦對象
        InterfaceProduct micomputer = Mifactory.createComputer();
        micomputer.get();
        // 經過小米工廠獲取小米手機對象
        InterfaceProduct miphone = Mifactory.createPhone();
        miphone.get();
        // 經過小米工廠獲取小米路由器對象
        InterfaceProduct mirouter = Mifactory.createRouter();
        mirouter.get();
    }
}

  運行結果:

 

  注意:經過上面的品牌擴展咱們發現,橫向擴展容易,縱向擴展很是困難,代碼能夠很是方便的擴展一個品牌已有的產品,但要擴展一個未定義的產品卻異常困難,好比要擴展一個華爲平板,須要修改工廠邏輯代碼,新增產品結構,這顯然不符合設計模式開閉原則,因此在使用時必定要考慮清楚,肯定不在有新的產品等級擴展。

六,優勢和缺點及使用場景

優勢

  • 抽象工廠模式隔離了具體類的生成, 使得客戶並不須要知道什麼被建立。 因爲這種隔離,更換一個具體工廠就變得相對容易, 全部的具體工廠都實現了抽象工廠中定義的那些公共接口, 所以只需改變具體工廠的實例, 就能夠在某種程度上改變整個軟件系統的行爲。

  • 當一個族中的多個對象被設計成一塊兒工做時, 它可以保證客戶端始終只使用同一個族中的對象。

  • 增長新的族很方便, 無須修改已有系統, 符合「開閉原則」。

缺點

  • 增長新的等級結構麻煩, 須要對原有系統進行較大的修改, 甚至須要修改抽象層代碼,這顯然會帶來較大的不便, 違背了「開閉原則」。

使用場景

  • 一個系統不該當依賴於具體類實例如何被建立、 組合和表達的細節, 這對於全部類型的工廠模式都是很重要的, 用戶無須關心對象的建立過程, 將對象的建立和使用解耦。

  • 系統中有多於一個的族, 而每次只使用其中某一族。 能夠經過配置文件等方式來使得用戶能夠動態改變族, 也能夠很方便地增長新的族。

  • 等級結構穩定, 設計完成以後, 不會向系統中增長新的等級結構或者刪除已有的等級結構。

 七,寫的不足之處還望批評指正

  寫的不足之處請在評論區指出,便於我及時更正錯誤,避免給讀者帶來誤解,但願你們多多提意見。

相關文章
相關標籤/搜索