天天看點

設計模式(二) 抽象工廠模式

前面我們說了工廠方法模式,當隻需要生産某一種類的時候可以使用。如果我們需要生産多類産品,就可以考慮使用抽象工廠模式。

抽象工廠模式的使用情景如下:

  • 系統需要多種産品,但是每次隻需要一組産品。
  • 産品種類較固定,産品的組合可能頻繁變化。

說得好像有點雲裡霧裡,是以先看一個例子吧。首先我們先來定義兩組産品接口,一個是調料,一個是食物。

public interface Food {
    String getFood();
}

public interface Spice {
    String getSpice();
}
           

然後我們來定義生産食物和調料的抽象工廠。

public interface AbstractFactory {
    Spice getSpice();

    Food getFood();
}
           

然後我們定義兩個具體工廠,一個生産蛋糕,一個生産辣條。注意這裡使用了Java 8的Lambda表達式。

public class CakeFactory implements AbstractFactory {
    @Override
    public Spice getSpice() {
        return () -> "糖";
    }

    @Override
    public Food getFood() {
        return () -> "蛋糕";
    }
}

public class LatiaoFactory implements AbstractFactory {
    @Override
    public Spice getSpice() {
        return () -> "辣椒";
    }

    @Override
    public Food getFood() {
        return () -> "辣條";
    }
}
           

然後我們擷取一下蛋糕和辣條。可以看到如果需要擷取某組産品(糖和蛋糕、辣椒和辣條),那麼抽象工廠模式非常适合。而且要建立新的産品組合也很簡單,隻需要實作一個新的具體工廠即可。

public void run() {
    AbstractFactory factory = new CakeFactory();
    Spice spice = factory.getSpice();
    Food food = factory.getFood();
    printSpiceAndFood(spice, food);
    factory = new LatiaoFactory();
    spice = factory.getSpice();
    food = factory.getFood();
    printSpiceAndFood(spice, food);
}
private static void printSpiceAndFood(Spice spice, Food food) {
    System.out.println("調料:" + spice.getSpice() + "," + "食物:" + food.getFood());
}
           

比如說我們要建立一個新的鹹鴨蛋工廠,也非常簡單。

public class SaltyEggFactory implements AbstractFactory {
    @Override
    public Spice getSpice() {
        return () -> "鹽";
    }

    @Override
    public Food getFood() {
        return () -> "鹹鴨蛋";
    }
}
           

那麼抽象工廠模式的缺點是什麼呢?其實從上面的例子中我們也可以看出來了。抽象工廠模式建立新的産品組合非常簡單(實作新的具體工廠),但是如果我們要增加新的産品種類,代碼就需要進行大量更改了。比方說我們現在需要添加一個餐具,那麼上面的抽象工廠類、三個具體類的代碼就必須全部進行更改。在實際情況中,這往往會破壞代碼開發者和使用者之間的協定。

說到這裡,抽象工廠模式的優缺點和使用場景也就呼之欲出了。如果系統中需要多種類型的産品,而産品的種類相對固定,不會出現新類型,這時候就可以使用抽象工廠模式。符合這種情景的都可以使用抽象工廠,例如為軟體更換界面,由于界面的标題欄、菜單欄等元件相對固定,是以這些可以聲明為一個抽象工廠,然後每一中界面樣式為一個具體實作工廠。