java設計模式——建立型之工廠三兄弟(3)
自大學課程初識設計模式以來,就越發覺得有必要系統學習一下設計模式。
剛好在實習前準備期間課比較少,抽出一點時間整理一下記一些筆記,複製貼上比較多。
筆記比較適合學習過設計模式的同學。
Abstract Factory Pattern(抽象工廠模式)
另外感謝劉偉博士,學習設計模式可以看劉偉博士的部落格,很詳盡。
抽象工廠模式的適用範圍
(1) 使用者無須關心物件的建立過程,將物件的建立和使用解耦。
(2) 系統中有多於一個的產品族,而每次只使用其中某一產品族。
(3) 屬於同一個產品族的產品將在一起使用。
這一約束必須在系統的設計中體現出來。
(4) 產品等級結構穩定。
設計完成之後,不會向系統中增加新的產品等級結構或者刪除已有的產品等級結構。
應用例項
在javaAPI中的應用例項最具代表性的是AWT在不同作業系統下表現的不同樣式。
在不同作業系統中,使用同樣的AWT程式碼(即使用相同的介面)創建出的窗體、按鈕等控制元件的樣式會隨作業系統的改變而改變。
抽象工廠模式如何實現
新概念:產品等級結構與產品族
(1) 產品等級結構
產品等級結構即產品的繼承結構,如一個抽象類是電視機,其子類有海爾電視機、海信電視機、TCL 電視機,則抽象電視機與具體品牌的電視機之間構成了一個產品等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。
(2) 產品族
在抽象工廠模式中,產品族是指由同一個工廠生產的,位於不同產品等級結構中的一組產品,如海爾電器工廠生產的海爾電視機、海爾電冰箱,海爾電視機位於電視機產品等級結構中,海爾電冰箱位於電冰箱產品等級結構中,海爾電視機、海爾電冰箱構成了一個產品族。
上圖比較好理解
角色
AbstractFactory(抽象工廠)
它聲明瞭一組用於建立一族產品的方法,每一個方法對應一種產品。
ConcreteFactory(具體工廠)
它實現了在抽象工廠中宣告的建立產品的方法,生成一組具體產品,這些產品構成了一個產品族,每一個產品都位於某個產品等級結構中。
AbstractProduct(抽象產品)
它為每種產品宣告介面,在抽象產品中聲明瞭產品所具有的業務方法。
ConcreteProduct(具體產品)
它定義具體工廠生產的具體產品物件,實現抽象產品介面中宣告的業務方法。
類圖
抽象工廠模式在工廠方法模式上的優化就是將需要賦予同等屬性的產品放在一個工廠中一起建立,可以複用原始產品;擴充套件工廠(產品族)方便,當然缺點就是若有新產品(產品等級結構)進入時就要修改工廠的程式碼了,違反了開閉原則。這裡有開閉原則的傾斜性。
抽象工廠模式的優缺點
主要優點
(1) 抽象工廠模式隔離了具體類的生成,使得客戶並不需要知道什麼被建立。由於這種隔離,更換一個具體工廠就變得相對容易,所有的具體工廠都實現了抽象工廠中定義的那些公共介面,因此只需改變具體工廠的例項,就可以在某種程度上改變整個軟體系統的行為。
(2) 當一個產品族中的多個物件被設計成一起工作時,它能夠保證客戶端始終只使用同一個產品族中的物件。
(3) 增加新的產品族很方便,無須修改已有系統,符合“開閉原則”。
主要缺點
增加新的產品等級結構麻煩,需要對原有系統進行較大的修改,甚至需要修改抽象層程式碼,這顯然會帶來較大的不便,違背了“開閉原則”。
練習
題目
在簡單工廠模式和工廠方法模式的問題的基礎上進行修改。
當我們需要建造不同顏色的圖形集時需要使用抽象工廠模式。
程式碼實現
抽象產品:Circle.java
package com.joy;
public interface Circle {
public void display();
}
抽象產品:Rectangle.java
package com.joy;
public interface Rectangle {
public void display();
}
具體產品:RedCircle.java
package com.joy;
public class RedCircle implements Circle{
@Override
public void display() {
System.out.println("顯示紅色的圓~");
}
}
具體產品:GreenCircle.java
package com.joy;
public class GreenCircle implements Circle{
@Override
public void display() {
System.out.println("顯示綠色的圓~");
}
}
具體產品:RedRectangle.java
package com.joy;
public class RedRectangle implements Rectangle{
@Override
public void display() {
System.out.println("顯示紅色的長方形~");
}
}
具體產品:GreenRectangle.java
package com.joy;
public class GreenRectangle implements Rectangle{
@Override
public void display() {
System.out.println("顯示綠色的長方形~");
}
}
抽象工廠:Factory.java
package com.joy;
public interface Factory {
public Circle getCircle();
public Rectangle getRectangle();
}
具體工廠:RedFactory.java
package com.joy;
public class RedFactory implements Factory {
@Override
public Circle getCircle() {
return new RedCircle();
}
@Override
public Rectangle getRectangle() {
return new RedRectangle();
}
}
具體工廠:GreenFactory.java
package com.joy;
public class GreenFactory implements Factory {
@Override
public Circle getCircle() {
return new GreenCircle();
}
@Override
public Rectangle getRectangle() {
return new GreenRectangle();
}
}
客戶端:AbstractFactoryDemo.java
package com.joy;
public class AbstractFactoryDemo {
public static void main(String[] args) {
Circle c;
Rectangle r;
Factory f;
System.out.println("客戶端:需要紅色");
f = new RedFactory();
f.getCircle().display();
f.getRectangle().display();
System.out.println("客戶端:需要綠色");
f = new GreenFactory();
f.getCircle().display();
f.getRectangle().display();
}
}
執行結果
總結
工廠模式主要都是為了實現客戶端和產品之間的解耦,這樣客戶端就能靈活獲取產品。抽象工廠模式會用到大系統中,主要是對相同樣式的不同產品進行一起管理,因此廣泛運用於樣式,其他例子我還沒有遇見。但是在寫程式碼理解的過程中發現其與裝飾模式有異曲同工的感覺,但是實現起來是不同的,可以進一步討論。