設計模式(四)——抽象工廠模式

本文屬于系列文章《設計模式》,附上文集鏈接
不知道看上一篇的時候,有沒有看到一個問題,如果只是簡單的工廠,為什么要一個抽象工廠類?那個抽象類完全沒必要啊,直接用一個工廠類,傳入class參數,不就行了嗎?這里就來了,抽象工廠模式。不過說實話,抽象得我快抽風了。。看了幾篇博客了,最后發現百度百科很強。

抽象工廠模式

  • 定義:為創建一組相關或相互依賴的對象提供一個接口,而且無須指定它們的具體類。
  • 作用:當每個抽象產品都有多于一個的具體子類的時候,工廠角色怎么知道實例化哪一個子類呢?比如每個抽象產品角色都有兩個具體產品。抽象工廠模式提供兩個具體工廠角色,分別對應于這兩個具體產品角色,每一個具體工廠角色只負責某一個產品角色的實例化。每一個具體工廠類只負責創建抽象產品的某一個具體子類的實例。
  • 是一個創建類模式

上面的定義和作用分別從書上和百度百科看到的,說實話,我并不是很懂,看了好幾篇博客,結合百度百科,我決定這篇寫成一篇可能會被人罵的文章。

首先還是上代碼,上看到個人覺得不恰當的例子的代碼:
大體是模仿工廠制造車吧

// 車接口
public interface CarModel {
    public void alarm();
    public void run();
}
// 實現CarModel接口的抽象車
public abstract class BenzCar implements CarModel{
    @Override
    public void alarm() {
        System.out.println("這是奔馳車");
    }
}
// 實現CarModel接口的抽象車
public abstract class BmwCar implements CarModel{
    @Override
    public void alarm() {
        System.out.println("這是寶馬車");
    }
}
// A系列的奔馳車
public class ABenzCar extends BenzCar{
    @Override
    public void run() {
        System.out.println("A系列的奔馳車在飛馳");
    }
}
// A系列的寶馬車
public class ABmwCar extends BmwCar{
    @Override
    public void run() {
        System.out.println("A系列的寶馬車在飛馳");
    }
}
// 還有B系列的車,是有兩個產品等級的,這里就不列出來了
// 抽象工廠
public abstract class AbstractCarFactory {
    // 為什么不能用泛型約束?
    // 因為用了泛型約束,就無法建立這個抽象對象,抽象工廠也就不復存在,為什么會建立不了這個抽象工廠呢?
    // 因為建立抽象工廠后,子類繼承之后,抽象方法接收的參數并不是某一個具體的產品的class屬性,這意味著,只要是符合這個類約束的子類的class屬性,都可以傳進來,這就沒有不同工廠這種概念了,所以抽象工廠也不存在,因為一個工廠就處理完了。
//  public abstract <T extends BenzCar> T  getBenzCar(Class<T> c);
//  public abstract  <T extends BmwCar> T  getBmwCar(Class<T> c);
    public abstract BenzCar getBenzCar();
    public abstract BmwCar getBmwCar();
}
// 具體工廠
public class ACarFactory extends AbstractCarFactory {
    @Override
    public BenzCar getBenzCar() {
        ABenzCar car = new ABenzCar();
        // doSomething
        return car;
    }
    @Override
    public BmwCar getBmwCar() {
        ABmwCar car = new ABmwCar();
        // doSomething
        return car;
    }
    /*@Override
    public <T extends BenzCar> T getBenzCar(Class<T> c) {
        T car = null;
        try {
            car = (T) Class.forName(c.getName()).newInstance();
            return car;
        } catch (Exception e) {
        }
        return car;
    }*/
}
//場景類
public class Client {
    public static void main(String[] args) {
        ACarFactory aCarFactory = new ACarFactory();
        BenzCar abenzCar =  aCarFactory.getBenzCar();
        abenzCar.alarm();
        abenzCar.run();
        System.out.println("--------------------");
        BmwCar abmwCar = aCarFactory.getBmwCar();
        abmwCar.alarm();
        abmwCar.run();
        System.out.println("--------------------");
        BCarFactory bCarFactory = new BCarFactory();
        BenzCar bbenzCar = bCarFactory.getBenzCar();
        bbenzCar.alarm();
        bbenzCar.run();
        System.out.println("--------------------");
        BmwCar bbmwCar = bCarFactory.getBmwCar();
        bbmwCar.alarm();
        bbmwCar.run();
    }
}
結果:
這是奔馳車
A系列的奔馳車在飛馳
\--------------------
這是寶馬車
A系列的寶馬車在飛馳
\--------------------
這是奔馳車
B系列的奔馳車在飛馳
\--------------------
這是寶馬車
B系列的寶馬車在飛馳

來分析下代碼,這段代碼我覺得很有問題的地方,就在于抽象出那個AbstractCarFactory有什么用,為什么這么說?在抽象工廠那里的注釋,我寫上了,如果只是單純地要劃分產品等級,那我直接實現泛型約束,就像我注釋掉
的代碼。

public abstract <T extends BenzCar> T getBenzCar(Class<T> c);
public abstract <T extends BmwCar> T getBmwCar(Class<T> c);

這樣的話,再建一個SuperFactory,超級工廠,根據傳進來的class屬性,就可以生產出相應的對象。可能有人會說,這個SuperFactory不符合單一職責原則啊,一個類做了多種事,好,那退而求次,選擇兩個類,分別生產A級產品和生產B級產品。然后就會有人說,那就對嘛,而兩個生產的方法還是相同的,為了日后好擴展,抽象共同部分出來作為父類,超棒的。但是有沒有想過,就像上面的代碼,我可以換一種抽象方式,就是BenzCarFactory和BmwCarFactory,然后專門用來生產Benz和Bmw,還可以用泛型約束,方法都省了一個,這樣有問題么?
就是因為有這樣的疑問,所以就不敢亂寫這篇東西,看了好幾篇博客,結合書上的例子,看了下百度百科(這個真的強,可能就是用大神的博文做的),最后我得到了這樣的一個理解:抽象工廠要解決的主要問題,是M個不同的產品族,M個產品族都有N個不同的等級,而每個等級的產品,都有共性!!!就是這個共性,才是使用抽象工廠的根本。

什么意思呢?用上文的代碼來講述,A系列的車和B系列的車,之所以要把它們分開兩個工廠去實現,抽取出生產車的抽象方法,是因為A系列的車和B系列的車分別有A系列車的共性和B系列車的共性。就比如說,A系列的車在組裝的時候要在方向盤那里銘一個“A”,B系列的車在組裝的時候要在方向盤那里銘一個“B”,如果沒用抽象工廠模式,用我上面那段話提的方法,要怎么實現呢?分別在BenzCarFactory和BmwCarFactory各自實現組裝A字的方法和組裝B字的方法。這樣有啥不好呢?代碼沒重用唄,因為這兩個方法都是一模一樣的。還有一個問題,假設共性不止一個,而是有很多個,想想是不是很可怕。
而在抽象工廠怎么實現呢?在ACarFactory直接寫A系列車共性的方法,在BCarFactory直接寫B系列車共性的方法,這樣就很完美了。

然后看完百度百科有點醍醐灌頂的時候,看到了一句話,在日常的編程中,工廠方法用得比抽象工廠要多!!!!好吧,給了我一記重錘。

以上,就是我對抽象工廠模式的理解。要打要罵評論區走起。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容