文章出處

1. 女媧的失誤

        上一節學習了工廠模式,女媧運用了該模式成功創建了三個人種,可是問題來了,她發現沒有性別……這失誤也忒大了點吧……竟然沒有性別,那豈不是……無奈,只好抹掉重來了,于是所有人都被消滅掉了,重新造人。

        女媧開始分析了,既然要區別男女,那么生產人種的工廠(八卦爐)要重新改造了,因為一個設備要么全男性,要么全女性。所以只能將八卦爐拆開了,把原先的一個變兩個,并且略加修改,變成女性八卦爐和男性八卦爐,這樣就可以了。于是女媧開始準備生產了,她先畫了個示意圖如下:

 

        這個圖雖然有點大,但是不復雜,她將HumanFactory接口用兩個新的接口繼承,分別帶有男性和女性特征;將原來具體的Human類也改成了抽象類,用兩個具體的Human類去繼承。下面我們看看女媧的實現:

        先看Human接口和它的幾個抽象類:

//定義抽象人類接口  
public interface Human {  
    public void getColor();  
    public void talk();  
    public void getSex(); //多了個性別  
}  
  
//定義抽象黃種人類  
public abstract class AbstractYellowHuman implements Human {  
    @Override  
    public void getColor() {  
        System.out.println("Yellow color");  
    }  
    @Override  
    public void talk() {  
        System.out.println("Yellow people");  
    }   
}   
//抽象黑種人和白種人就不寫了,跟抽象黃種人道理一樣  
////黃種人男性類  
public class MaleYellowHuman extends AbstractYellowHuman {  
    @Override  
    public void getSex() {  
        System.out.println("Yellow man!");  
    }  
}  
//黃種人女性類略  

 以上省略了類似的代碼,實現方式都一樣,很簡單,就不啰嗦了,到此為止,女媧把人種都定義好了,下面就是去定義八卦爐了:

//抽象工廠接口的定義  
public interface HumanFactory {  
    public Human createYellowHuman();  
    public Human createBlackHuman();  
    public Human createWhiteHuman();  
}  
  
//生產女性的八卦爐  
public class FemaleFactory implements HumanFactory {  
    @Override  
    public Human createYellowHuman() {  
        return new FemaleBlackHuman();  
    }  
    @Override  
    public Human createBlackHuman() {  
        return new FemaleBlackHuman();  
    }  
    @Override  
    public Human createWhiteHuman() {  
        return new FemaleWhiteHuman();  
    }  
}  
  
//生產男性的八卦爐  
public class MaleFactory implements HumanFactory {  
    @Override  
    public Human createYellowHuman() {  
        return new MaleYellowHuman();  
    }  
    @Override  
    public Human createBlackHuman() {  
        return new MaleBlackHuman();  
    }  
    @Override  
    public Human createWhiteHuman() {  
        return new MaleWhiteHuman();  
    }  
}  

好了,現在人種有了,八卦爐也有了,女媧終于可以再次造人了!

public class NvWa {  
    public static void main(String[] args) {  
        HumanFactory maleHumanFactory = new MaleFactory(); //第一條生產線:男性生產線  
        HumanFactory femaleHumanFactory = new FemaleFactory(); //第二條生產線:女性生產線  
          
                //生產線建立完畢,開始造人  
        Human maleYellowHuman = maleHumanFactory.createYellowHuman(); //造黃色男性  
        Human femaleYellowHuman = femaleHumanFactory.createYellowHuman(); //造黃色女性  
          
        System.out.println("--生產一個黃色女性--");  
        femaleYellowHuman.getColor();  
        femaleYellowHuman.talk();  
        femaleYellowHuman.getSex();  
          
        System.out.println("--生產一個黃色男性--");  
        maleYellowHuman.getColor();  
        maleYellowHuman.talk();  
        maleYellowHuman.getSex();  
        /* 
         * …… 
         */  
    }  
}  

到這里,抽象工廠模式的思路算是理清了,下面看看抽象工廠模式的定義。

 

2. 抽象工廠模式的定義

        抽象工廠模式(Abstract Factory Pattern)是一種比較常用的模式,其定義如下:

Provide an interface for creating families of related or dependent objects without specifying their concrete classes. 即為創建一組相關或相互依賴的對象提供一個接口,而且無須指定它們的具體類。它的通用類圖如下:

        抽象工廠模式是工廠模式的升級版,在有多個業務品種、業務分類時,通過抽象工廠模式產生需要的對象是一種非常好的解決方式。我們來看看抽象工廠歐式的通用源代碼,首先有兩個互相影響的產品線(也叫產品族),例如汽車的左門和右門,這兩個數量應該是相等的——兩個對象之間的約束,每個型號的車門都是不一樣的,這是產品等級結構約束的,我們先看看兩個產品族的類圖:

        注意類圖上的圈圈、框框相對應,兩個抽象的產品類可以有關系,例如共同繼承或實現一個抽象類或接口,其源代碼如下:

public abstract class AbstractProductA {  
    //每個產品共有的方法  
    public void shareMethod() {  
      
    }  
    //每個產品相同的方法,不同的實現  
    public abstract void doSomething();   
}   

 兩個具體的產品實現類的代碼如下:

public class productA1 extends AbstractProductA {  
    public abstract void doSomething(){  
        System.out.println("產品A1的實現方法");  
    }  
}   
  
public class productA2 extends AbstractProductA {  
    public abstract void doSomething(){  
        System.out.println("產品A2的實現方法");  
    }  
}   

 產品B與此類似,不再贅述。抽象工廠類AbstractCreator的職責是定義每個工廠要實現的功能,在通用代碼中,抽象工廠類定義了兩個產品族的產品創建,如下:

public abstract class AbstractCreator {  
    //創建A產品家族  
    public abstract AbstracProductA createProductA();  
    //創建B產品家族  
    public abstract AbstracProductB createProductB();  
    //如果有N個產品族,這里就應該有N個創建方法  
}   

 如何創建一個產品呢?這是由具體的實現類來完成的,Creator1和Creator2代碼如下:

public class Creator1 extends AbstractCreator {  
    //只生產產品等級為1的A產品  
    public AbstracProductA createProductA(){  
        return new ProductA1();  
    }  
    //只生產產品等級為1的B產品  
    public AbstracProductB createProductB() {  
        return new ProductB1();  
    }   
}   
  
public class Creator2 extends AbstractCreator {  
    //只生產產品等級為1的A產品  
    public AbstracProductA createProductA(){  
        return new ProductA2();  
    }  
    //只生產產品等級為1的B產品  
    public AbstracProductB createProductB() {  
        return new ProductB2();  
    }   
}   

注:有M個產品等級就應該有M個實現工廠類,在每個實現工廠中,實現不同產品族的生產任務。

 

       在具體的業務中就可以生產一個與實現無關的對象了,如:

public class AbstractFactoryTest {  
    public static void main(String[] args) {  
        AbstractCreator creator1 = new Creator1();  
        AbstractCreator creator2 = new Creator2();  
        AbstractProductA a1 = creator1.createProductA();  
        AbstractProductA a2 = creator2.createProductA();  
  
        AbstractProductB b1 = creator1.createProductB();  
        AbstractProductB b2 = creator2.createProductB();  
  
        //……  
    }  
}  

3. 抽象工廠模式的優缺點

3.1 優點

        1)封裝性。每個產品的實現類不是高層模塊要關心的,它要關心的是接口,是抽象,它不關心對象是如何創建出來的,這都由工廠類負責的,只要知道工廠類是誰,我就能創建一個需要的對象,省時省力。

        2)產品族內的約束為非公開狀態。例如生產男女比例的問題上,猜想女媧娘娘肯定有自己的打算,那么在抽象工廠模式中,這些約束都在工廠內里面實現的。

3.2 缺點

        抽象工廠模式最大的缺點就是產品族擴展非常困難。如果我們要增加一個產品C,也就是說產品族由原來的A和B增加到3個,那么我們首先要在抽象類AbstractCreator中增加createProductC()方法,然后兩個實現類都要修改……說到這里,已經知道了擴展的弊端了……

        注意這里是產品族擴展比較困難,而不是產品等級擴展困難。產品等級擴展還是非常容易的,增加一個產品等級,只要增加一個工廠類負責新增加出來的產品生產任務即可。也就是說橫向擴展容易,縱向擴展難。

        抽象工廠模式就介紹這么多,如有錯誤之處,歡迎留言指正~


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()