工廠模式有簡單工廠模式
工廠方法模式和抽象工廠模式幾種形態
其中簡單工廠模式和工廠方法模式已經在前面作過介紹
在這裡
我們來介紹抽象工廠模式
抽象工廠模式是所有形態的工廠模式中最為抽象和最具廣泛性的一種形態
抽象工廠模式的定義
抽象工廠模式是工廠方法模式的進一步擴廣化和抽象化
我們給出抽象工廠模式的類圖定義如下
圖
抽象工廠模式的類圖定義
從上圖可以看出
簡單工廠模式涉及到以下的角色
抽象工廠(AbstractFactory)類或接口
擔任這個角色的是工廠方法模式的核心
它是與應用程序無關的
任何在模式中創立對象的工廠類必須實現這個接口
或繼承這個類
實工廠類 (Conrete Factory)
擔任這個角色的是與應用程序緊密相關的
直接在應用程序調用下
創立產品實例的那樣一些類
抽象產品 (Abstract Product)
擔任這個角色的類是工廠方法模式所創立的對象的父類
或它們共同擁有的接口
實產品 (Concrete Product)
擔任這個角色的類是工廠方法模式所創立的任何對象所屬的類
怎麼這個類圖和工廠方法模式的類圖看起來是一樣的?
是的
圖是一樣的
但是含義有很大的不同
必須指出
在抽象工廠模式中
抽象產品 (AbstractProduct) 可能是一個或多個
從而構成一個或多個產品族(Product Family)
在只有一個產品族的情況下
抽象工廠模式實際上退化到工廠方法模式
在上面的類圖中
只給出了一個產品族
相當於位圖中的一個點
而完整的位圖應當是三維的
如下圖
圖
抽象工廠模式的位圖
從位圖可以清楚地看到
與紙面垂直的數軸
即第三維軸
是代表產品族的數軸
上面的位圖中展示的是有兩個產品族
族A和族B的情形
在只有一個產品族時
第三維就坍縮掉
位圖也就只剩下兩維
這時抽象工廠模式就退化得與工廠方法模式一模一樣
在什麼情形下應當使用抽象工廠模式
在以下情況下
應當考慮使用抽象工廠模式
首先
一個系統應當不依賴於產品類實例被創立
組成
和表示的細節
這對於所有形態的工廠模式都是重要的
其次
這個系統的產品有多於一個的產品族
第三
同屬於同一個產品族的產品是設計成在一起使用的
這一約束必須得在系統的設計中體現出來
最後
不同的產品以一系列的接口的面貌出現
從而使系統不依賴於接口實現的細節
其中第二丶第三個條件是我們選用抽象工廠模式而非其它形態的工廠模式的關鍵性條件
抽象工廠模式在小花果園系統中的實現
現在
我們在佛羅裡達的渡假小屋修整好啦
接下來
一項重要而光榮的工作
就是開發小屋後面的小花園
這意味著
我們有兩處小花園需要照料
一處在北方地區
另一處在亞熱帶地區
抽象工廠模式正好適用於我們的情況
圖
抽象工廠模式應用於小花果園系統中
三種不同的背景顏色可以區分工廠類
蔬菜類(第一產品族)
和水果類的類圖(第二產品族)
兩處花園就相當於兩個產品族
顯然
給北方花園的植物是要種植在一起的
給南方花園的植物是要另種植在一起的
這種分別應當體現在系統的設計上面
這就滿足了應當使用抽象工廠模式的第二和第三個條件
package com
javapatterns
abstractfactory;
public interface Gardener {}
代碼清單
接口 Gardener
package com
javapatterns
abstractfactory;
public class NorthenGardener implements Gardener
{
public VeggieIF createVeggie(String name) { return new NorthernVeggie(name); }
public FruitIF createFruit(String name) { return new NorthernFruit(name); }
}
代碼清單
實工廠類 NorthenGardener
package com
javapatterns
abstractfactory;
public class TropicalGardener implements Gardener
{
public VeggieIF createVeggie(String name) { return new TropicalVeggie(name); }
public FruitIF createFruit(String name) { return new TopicalFruit(name); }
}
代碼清單
實工廠類 TropicalGardener
package com
javapatterns
abstractfactory;
public interface VeggieIF {}
代碼清單
接口 VeggieIF
package com
javapatterns
abstractfactory;
public class NorthernVeggie implements VeggieIF
{
public NorthernVeggie(String name) { this
name = name; }
public String getName(){ return name; }
public void setName(String name){ this
name = name; }
private String name;
}
代碼清單
實產品類 NorthernVeggie
實產品類 NorthernFruit 與此極為類似
故略去
package com
javapatterns
abstractfactory;
public class TropicalVeggie implements VeggieIF
{
public TropicalVeggie(String name) { this
name = name;}
public String getName(){ return name; }
public void setName(String name){ this
name = name; }
private String name;
}
代碼清單
實產品類 TropicalVeggie
實產品類 TropicalFruit 與此極為類似
故略去
筆者對植物的了解有限
為免遺笑大方
在上面的系統裡采用了簡化處理
沒有給出高緯度和低緯度的水果類或蔬菜類的具體名稱
抽象工廠模式的另一個例子
這個例子講的是微型計算機的生產
產品族有兩個
PC(IBM系列)和Mac(MacIntosh系列)
顯然
我們應該使用抽象工廠模式
而不是工廠方法模式
因為後者適合於處理只有一個產品族的情形
圖
抽象工廠模式應用於微型計算機生產系統中
兩種不同的背景顏色可以區分兩類產品族
及其對應的實工廠類
關於模式的實現
在抽象實現工廠模式時
有下面一些值得注意的技巧
第一丶實工廠類可以設計成單態類
很顯然
在小花果園系統中
我們只需要 NorthenGardener 和TropicalGardener 的一個實例就可以了
關於單態類的知識
請見<爪哇語言單態類創立性模式>
第二丶在實現抽象工廠模式時
產品類往往分屬多於一個的產品族
而針對每一族
都需要一個實工廠類
在很多情況下
幾個實工廠類都彼此相象
只有些微的差別
這時
筆者建議使用原始模型(Prototype)模式
這一模式會在以後介紹
屆時作者會進一步闡述這一點
第三丶設計更加靈活的實工廠
以微型計算機生產系統為例
PCProducer 是一個實工廠類
它的不靈活之處在於
每一種產品都有一個工廠方法
CPU 有createCPU()
RAM 有createRAM()
等等
如果一個已有的系統需要擴充
比如增加硬盤這一新產品
我們就需要增加一系列的接口 (createHD())丶類(HD
PCHD
MacHD)和方法
這似乎不很理想
一個解決的辦法是
把createCPU()
createRAM()
createHD()這幾個方法合並為一個createPart(String type)方法
這個合並後的方法返還一個Part接口
所有的產品都要實現這一接口
而CPU
RAM
和HD接口則不再需要了
每一個實產品都需要有一個屬性
表明它們的種類是CPU
RAM
和HD
這樣做的結果是
數據類型的豐富結構被扁平化了
客戶端拿到的永遠是一個Part接口
這對客戶端而言不很安全
第四丶抽象工廠類可以配備靜態方法
以返還實工廠
設計的方法有兩種
一種是以一個靜態方法
按照參量的值
返回所對應的實工廠
靜態方法的數據類型是抽象方法類
另一種是以每一個實工廠類都配備一個靜態方法
其數據類型是該實工廠類
問答題
第
題
如上面的討論
抽象工廠類可以配備一個靜態方法
按照參量的值
返回所對應的實工廠
請把微型計算機生產系統的抽象工廠類按照這一方案改造
給出UML類圖和源代碼
第
題
如上面的討論
抽象工廠類可以配備一系列靜態方法對應一系列的實工廠
請把微型計算機生產系統的抽象工廠類按照這一方案改造
給出UML類圖和源代碼
第
題
如上面的討論
實工廠類可以設計成單態類
請在第
題的基礎上把微型計算機生產系統的實工廠類按照這一方案改造
給出UML類圖和源代碼
問答題答案
第
題
微型計算機生產系統的抽象工廠原本是接口
現在需要改造成抽象類
圖
三種不同的背景顏色可以區分抽象工廠類
兩類產品族
及其對應的實工廠類
ComputerProducer 類圖中類名為斜體表明該類是抽象的
而getProducer()的下劃線表明該方法是靜態的
package com
javapatterns
abstractfactory
exercise
;
public class ComputerProducer
{
public static ComputerProducer getProducer(String which)
{
if (which
equalsIgnoreCase(
PC
))
{
return new PCProducer();
}
else (which
equalsIgnoreCase(
Mac
))
{
return new MacProducer();
}
}
}
代碼清單
抽象類 ComputerProducer 的方法 getProducer(String which)
第
題
略
第
題
本題答案是在第
題基礎之上的
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27318.html