1.抽象工廠模式介紹
抽象工廠模式(Abstract Factory Pattern),也是創建型設計模式之一。大家聯想一下現實生活中的工廠肯定都是具體的,那麼抽象工廠意味着生產出來的產品是不是確定的,那這豈不是很奇怪?抽象工廠模式起源於以前對不同操作系統的圖形化解決方案,如不同的操作系統中的按鈕和文本框控件其實現不同,展示效果也不一樣,對於每一個操作系統,其本身就構成一個產品類,而按鈕與文本框控件也構成一個產品類,兩種產品類兩種變化,各自有自己的特性,如Android中的Button和TextView 、ios中的Button和TextView等等。
2.抽象工廠模式的定義
爲創建一組相關或者是相互依賴的對象提供一個接口,而不需要制定它們的具體類。
3,抽象工廠模式的使用場景
一個對象族有相同的約束時可以使用抽象工廠模式。是不是聽起來很抽象?舉個例子,Android、ios、Window Phone下都有短信軟件和撥號軟件,兩者都屬於Software軟件的範疇,但是,它們梭子啊的操作系統平臺不一樣,即便是同一家公司出品的軟件,其代碼的實現邏輯也是不同的,這時候就可以考慮使用抽象工廠方法模式來產生Android、ios、Window Phone下的短信軟件和撥號軟件。
4.抽象工廠模式的UML類圖
根據類圖可以得出如下一個抽象工廠模式的通用模式代碼:
抽象產品類A:
public abstract class AhstractProductA {
/*
* 每個具體的產品子類需要實現的方法
*/
public abstract void method();
}
抽象產品類B:
public abstract class AhstractProductB {
/*
* 每個具體的產品子類需要實現的方法
*/
public abstract void method();
}
具體產品:
//具體產品類A1
public class ConcreteProductA1 extends AhstractProductA{
@Override
public void method() {
System.out.println("具體產品A1 的方法");
}
}
//具體產品類A2
public class ConcreteProductA2 extends AhstractProductA{
@Override
public void method() {
System.out.println("具體產品A2 的方法");
}
}
//具體產品類B1
public class ConcreteProductB1 extends AhstractProductB{
@Override
public void method() {
System.out.println("具體產品B1 的方法");
}
}
//具體產品類B2
public class ConcreteProductB2 extends AhstractProductB {
@Override
public void method() {
System.out.println("具體產品B2 的方法");
}
}
抽象工廠類:
public abstract class AbstractFactory {
/*
* 創建產品A 的方法
*
* @return 產品A對象
*/
public abstract AhstractProductA createProductA();
/*
* 創建產品B 的方法
*
* @return 產品B對象
*/
public abstract AhstractProductB createProductB();
}
具體工廠類:
//具體工廠類1
public class ConcreteFactory1 extends AbstractFactory {
@Override
public AhstractProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public AhstractProductB createProductB() {
return new ConcreteProductB1();
}
}
//具體工廠類2
public class ConcreteFactory2 extends AbstractFactory {
@Override
public AhstractProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public AhstractProductB createProductB() {
return new ConcreteProductB2();
}
}
雖然抽象工廠方法模式的類繁多,但是,主要還是分爲4類:
- AbstractFactory: 抽象工廠角色,它聲明瞭一組用於創建一種產品的方法,每一個方法對應一種產品,如上述類圖中的AbstrctFactory中就定義了兩個方法,分別創建產品A和B.
- ConcreteFactory:具體工廠角色,它實現了在抽象工廠中定義的創建產品的方法,生成一組具體產品,這些產品構成了一個產品類,每一個產品都位於某個產品等級結構中,如上述類圖中ConcreteFactory1和ConcreteFactory2。
- AbstractProduct:抽象產品角色,它爲每種產品聲明接口,比如上述類圖中的AbstractProductA和AbstractProductB.
- ConcreteProduct:具體產品角色,它定義具體工廠生產的具體產品對象,實現抽象產品接口中聲明的業務方法,如上述圖中ConcreteProductA1、ConcreteProductA2、ConcreteProductB1、ConcreteProductB2。
5.抽象工廠方法模式的簡單實現
在工廠方法模式中,以小明的車廠爲例闡述了工廠方法模式,但是,後來小明發現一個問題,雖然Q3、Q5、Q7都是一個車系,但是三者之間的零部件差別卻是很多,就拿Q3和Q7說,Q3使用的發動機是國產的,而Q7則原裝進口的;Q3輪胎時普通輪胎,而Q7是全尺寸越野輪胎;還有Q3使用的是比較普通的制動系統,而Q7則使用的制動性能更好的制動系統。Q3、Q7對應的是一系列車,而發動機、輪胎、制動系統則對應得一系列零部件,兩者是兩種不同的產品類型,這時候就可以將抽象工廠模式應用到其中,首先,汽車工廠需要生產輪胎、發動機、制動系統這3種部件。
抽象車廠類:
public abstract class CarFactory {
/*
* 生產輪胎
*
* @return 輪胎
*/
public abstract ITire createTire();
/*
* 生產發動機
*
* @return 發動機
*/
public abstract IEngine createEngine();
/*
* 生產製動系統
*
* @return 制動系統
*/
public abstract IBrake createBrake();
}
輪胎相關類:
public interface ITire {
/*
* 輪胎
*/
void tire();
}
public class NormalTire implements ITire {
public void tire() {
System.out.println("普通輪胎");
}
}
public class SUVTire implements ITire {
public void tire() {
System.out.println("越野輪胎");
}
}
發動機相關類:
public interface IEngine {
/*
* 發動機
*/
void engine();
}
public class DomesticEngine implements IEngine{
public void engine() {
System.out.println("國產發動機");
}
}
public class ImportEngine implements IEngine{
public void engine() {
System.out.println("進口發動機");
}
}
制動系統類:
public interface IBrake {
/*
* 制動系統
*/
void brake();
}
public class NormalBrake implements IBrake{
public void brake() {
System.out.println("普通制動系統");
}
}
public class SeniorBrake implements IBrake{
public void brake() {
System.out.println("高級制動系統");
}
}
對於生產Q3的工廠,其使用的零部件不同,而生產Q7的工廠,其使用的零部件也不同。
Q3工廠類:
public class Q3Factory extends CarFactory{
@Override
public ITire createTire() {
return new NormalTire();
}
@Override
public IEngine createEngine() {
return new DomesticEngine();
}
@Override
public IBrake createBrake() {
return new NormalBrake();
}
}
Q7工廠類:
public class Q7Factory extends CarFactory{
@Override
public ITire createTire() {
return new SUVTire();
}
@Override
public IEngine createEngine() {
return new ImportEngine();
}
@Override
public IBrake createBrake() {
return new SeniorBrake();
}
}
最後,我們在Client客戶端中模擬:
public class Client {
public static void main(String[] args) {
// 構造一個生產Q3的工廠
CarFactory factoryQ3 = new Q3Factory();
factoryQ3.createTire().tire();
factoryQ3.createEngine().engine();
factoryQ3.createBrake().brake();
System.out.println("--------------------");
// 構造一個生產Q7的工廠
CarFactory factoryQ7 = new Q7Factory();
factoryQ7.createTire().tire();
factoryQ7.createEngine().engine();
factoryQ7.createBrake().brake();
}
}
輸出:
普通輪胎
國產發動機
普通制動系統
--------------------
越野輪胎
進口發動機
高級制動系統
上面我們只是模擬了兩個車系Q3和Q7的工廠,如何此時我們需求增加Q5的工廠呢?那麼對應的輪胎、制動系統和發動機類又要增加,這裏就可以看到抽象工廠方法模式的一個弊端,就是類的突增,如果工廠類過多,勢必導致類文件非常多,因此,在實際開發中一定要權衡慎用。
6.總結
優點:
一個顯著的優點是分離接口與實現,客戶端使用抽象工廠來創建需要的對象,而客戶端根本就就不知道具體的實現是誰,客戶端只是面向產品的接口編程而已,使其從具體的產品實現中解耦,同時基於接口與實現的分離,使抽象該工廠模式在切換產品類時更加靈活、容易。
缺點:
一是類文件的爆炸性增加,而是不太容易擴展新的產品類,因爲每當我們增加一個產品類就需要修改抽象工廠,那麼所有的具體工廠類均會被修改。