抽象工廠模式

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.總結

優點
一個顯著的優點是分離接口與實現,客戶端使用抽象工廠來創建需要的對象,而客戶端根本就就不知道具體的實現是誰,客戶端只是面向產品的接口編程而已,使其從具體的產品實現中解耦,同時基於接口與實現的分離,使抽象該工廠模式在切換產品類時更加靈活、容易。
缺點
一是類文件的爆炸性增加,而是不太容易擴展新的產品類,因爲每當我們增加一個產品類就需要修改抽象工廠,那麼所有的具體工廠類均會被修改。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章