抽象工廠模式
GOF的設計模式一書中是這樣定義:為建立一組相關或互相依賴的對象提供一個接口,無需指定它們的具體類。在java程式中,它可以是接口或者抽象類。
抽象工廠模式包含:
(1)、一系列互相關聯的産品類,這些産品類具有相同的結構;
(2)、一系列實的工廠類,實作由抽象工廠類提供的接口。每個工廠類生産一組相關的 産品了類對象。
當客戶需要從一個相關的産品類對象中建立一個對象,而沒有必要知道到底建立哪個對象時,可以使用抽象工廠模式。抽象工廠模式的類圖如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LcZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39zNwYjM1cTN2EjNxETM2EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
考慮如下問題:
設計一個米粉的銷售查詢系統,查詢不同米粉的價格,介紹等。為簡單起見,考慮兩種米粉:一種是柳州螺蛳粉(Snail powder),另一種是桂林米粉(Guilinpowder)。并且每種米粉都有二兩和三兩兩個等級。鑒于柳州螺蛳粉和桂林米粉兩類,以及他們都有相同的結構,可以考慮使用抽象工廠模式來設計銷售查詢系統,設計類圖如下:
假設你想要檢視柳州螺蛳粉,并且你想要三兩的,好,工廠滿足你,下面是具體的代碼實作。
首先是生産米粉的工廠,即(RiceNoodlesFactory)
public interface RiceNoodlesFactory {
//用于擷取柳州螺蛳粉對象
public SnailPowder getSnailPowder();
//用于擷取桂林米粉對象
public GuilinPowder getGuilinPowder();
}
接着是建立三兩的米粉的工廠(SuperRiceNoodlesFactory)
public class SuperRiceNoodlesFactory implements RiceNoodlesFactory {
//建立一個對象
@Override
public SnailPowder getSnailPowder() {
return new SuperSnailPower();
}
//建立一個對象
@Override
public GuilinPowder getGuilinPowder() {
return new SuperGuilinPowder();
}
}
然後是建立二兩米粉的工廠(MediumRiceNoodlesFactory)
public class MediumRiceNoodlesFactory implements RiceNoodlesFactory {
//建立一個對象
@Override
public SnailPowder getSnailPowder() {
return new MediumSnailPowder();
}
//建立一個對象
@Override
public GuilinPowder getGuilinPowder() {
return new MediumGuilinPowder();
}
}
接下來使柳州螺蛳粉的接口(SnailPowder)
public interface SnailPowder {
// 擷取關于柳州螺蛳粉的資訊
public String getSnailPowderInfo();
}
然後是其實作類,一個三兩的柳州螺蛳粉(SuperSnailPower)
public class SuperSnailPower implements SnailPowder {
public final String INFO = "這是一個三兩的柳州螺蛳粉,要7元";
@Override
public String getSnailPowderInfo() {
return INFO;
}
}
接下來是二兩的柳州 (MediumSnailPowder)
public class MediumSnailPowder implements SnailPowder {
public final String INFO = "這是一個二兩的柳州螺蛳粉,要6元";
@Override
public String getSnailPowderInfo() {
return INFO;
}
}
然後就是桂林米粉啦(GuilinPowder)
public interface GuilinPowder {
// 擷取關于桂林米粉的資訊
public String getGuilinPowderInfo();
}
小二,來一個三兩的桂林米粉,好咧(SuperGuilinPowder)
public class SuperGuilinPowder implements GuilinPowder {
public final String INFO = "這是一個三兩的桂林米粉,要5元";
@Override
public String getGuilinPowderInfo() {
return INFO;
}
}
三兩太多,好的,換二兩(MediumGuilinPowder)
public class MediumGuilinPowder implements GuilinPowder {
public final String INFO = "這是一個二兩的桂林米粉,要4元";
@Override
public String getGuilinPowderInfo() {
return INFO;
}
}
終于到客戶點餐啦(ClientGUI),一個三兩的柳州螺蛳粉,加變态辣,好的
public class ClientGUI {
public static void main(String[] args) {
//建立一個三兩螺蛳粉的對象工廠
RiceNoodlesFactory rnf = new SuperRiceNoodlesFactory();
//擷取一個三兩螺蛳粉的對象
SnailPowder snailPowder = rnf.getSnailPowder();
//擷取該對象的資訊
String snailPowderInfo = snailPowder.getSnailPowderInfo();
System.out.println(snailPowderInfo);
}
}
至此,終于搞定了,哈,下面來讨論一下抽象工廠模式
抽象工廠模式的擴充性:
1、在本例中,假如客戶要求有四兩的螺蛳粉和桂林米粉,好,在給每個米粉接口下面添加一個四兩米粉的實作即可,然後再增加一個建立四兩米粉的工廠類方法,此種情況下符合開閉原則。
2、加後來又新增加了一種米粉,老友粉,此時,則要修改建立米粉的兩個工廠類了,這時不不符合開閉原則。
總結一下
無論是簡單工廠模式,工廠方法模式,還是抽象工廠模式,他們都屬于工廠模式,在形式和特點上也是極為相似的,工廠模式最終目的都是為了解耦合。在使用時,我們不必去在意這個模式到底工廠方法模式還是抽象工廠模式,因為他們之間的演變常常是令人琢磨不透的。 抽象工廠模式相對于工廠方法模式來說,每個具體工廠可以生産一族産品(即多種産品);而工廠方法模式是具體工廠生産相應的具體産品,隻能生産一種産品。當産品族中隻有一種産品時抽象工廠模式退化成工廠方法模式。