工廠模式——(Head first設計模式4)


所謂工廠,肯定是和生產有關。工廠模式主要包括工廠方法模式和抽象工廠模式,有些人把簡單工廠也作為一種模式,在本文我分別討論簡單工廠模式,工廠方法模式,抽象工廠模式。這些模式中同樣也和生產有關。接下來,我們來看看各種工廠的特點。

簡單工廠模式

上面說了只是有些人把簡單工廠看做是設計模式,其實是一種編程習慣,無論是否是設計模式,本文將先看看其用法,然后簡單給出其類圖,最后說出其特點。

本節將面對多種比薩,先看看當顧客需要一個比薩時的過程:

1.根據類型,制作一個比薩形狀。2.然后進行烘烤3.切4.打包

如果不熟悉的話,完全可以把其想想成面包的做法。

當顧客根據自己的需求要一個比薩時,用代碼模擬這個過程如下:

public  class Pizza
    {
       public void bake() { }
       public void cut() { }
       public void box() { }
    }
    public class CheesePizza:Pizza
    {
        public CheesePizza()
        { }
    }
    public class GreekPizza : Pizza
    {
        public GreekPizza(){}
    }
    public class PepperoniPizza:Pizza
    {
        public PepperoniPizza() { }
    }
    public  class Store
    {
      public  Pizza OrderPizza(string type)
        {
            Pizza pizza = null;
            if (type=="Cheese")
            {
                pizza = new CheesePizza();
            }
            else if (type=="Greek")
            {
                pizza = new GreekPizza();
            }
            else if (type == "Pepperoni")
            {
                pizza = new PepperoniPizza();
            }
            pizza.bake();
            pizza.cut();
            pizza.box();
            return pizza;
        }
    }

以上的設計方法和我們的以前提到的過的原則(找出經常變化的部分,抽象成類),很明顯在if else 的地方發生經常性變化。

接下來就把if else 放到一個類中。修改后的代碼

public  class Store
{
  public  Pizza OrderPizza(string type)
    {
        Pizza pizza = null;
        //if (type=="Cheese")
        //{
        //    pizza = new CheesePizza();
        //}
        //else if (type=="Greek")
        //{
        //    pizza = new GreekPizza();
        //}
        //else if (type == "Pepperoni")
        //{
        //    pizza = new PepperoniPizza();
        //}
        SimpleFactory factory = new SimpleFactory();
        pizza =factory.CreatePizza(type);
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

public class SimpleFactory
{
    public Pizza CreatePizza(string type)
    {
        Pizza pizza = null;
        if (type == "Cheese")
        {
            pizza = new CheesePizza();
        }
        else if (type == "Greek")
        {
            pizza = new GreekPizza();
        }
        else if (type == "Pepperoni")
        {
            pizza = new PepperoniPizza();
        }
        return pizza;
    }
}

這樣的話,就可以遵循了把變化的部分抽象成一個類。下次需要變化,只需要對變化的類的部分做修改即可。下面給出其UML圖。

image

簡單工廠的目的,主要負責實現生產對象的細節,根據訂單來生產。每一個商店有對應着自己的工廠。在此,可以將OrderPizza是工廠的一個客戶,當然還可以是其他類似的方法,比如PizzaShopMenu也可以是工廠的客戶。客戶就是為了獲取工廠生成的對象。前者是為了賣給people,后者是為了使用Pizza類獲取其描述和價格等。這樣遵循了找出變化的部分,將其封裝到一個類中的原則,從而到達了復用的目的。

簡單工廠之所以簡單是因為它只根據需要,來生產出來指定的Pizza。特點:所有的產品都由一個工廠來生產。

接下來我們來看看工廠方法的實現。

工廠方法模式

如果是有多個商店,各個商店對於相同名字的pizza都有自己的生成方法。而且,除了生成方法不一樣,其他的烘烤,切,打包,都是使用一樣的步驟。下面就該我們的工廠方法模式出廠了。

由於生產pizza的方法決定於各個商店,不妨假設有兩個商店。其公共的基類,應該有一個抽象的生產方法,具體的生產方法決定於商店。其UML類圖如下:

image

上面的PizzaStore是一個抽象類,該類具有一個CreatePizza的抽象方法,真正實現的是具體的商店。

除了有多種商店,每個商店有多種Pizza類,而且是Pizza名是相同的,只是地區不一樣,下面Pizza類的命名方式為:地區+Pizza名,其UML類圖為:

image

商店和pizza的大致聯系如下圖:

image

在工廠方法中,使用了一個重要的原則:

原則五:依賴倒置:依賴於抽象,不要依賴於具體類

如果沒有使用上述原則,而是直接讓店鋪依賴於每個Pizza類。

image

如果Pizza的實現變化了,就必須改變PizzaStore。每增加一個Pizza都會增加一個依賴。如果使用工廠方法設計模式的話,其依賴於抽象,不依賴與具體類。我們可以抽象出一個Pizza類,讓所有商店以及所有的Pizza類來依賴它。這里涉及到一個依賴倒置的另一種解釋,高層組件和底層組件都依賴於抽象。而不依賴與具體的實現,高層組件是有底層組件的方法構建 而成的。PizzaStore是由Pizza的Bake,Cut,Box方法構建。那么根據這個原則其大致圖為:

image

這樣的設計方法,對於任何添加新的Pizza種類,不會影響到PizzaStore。從而實現了松耦合的效果。

工廠方法和簡單工廠設計模式的區別:簡單工廠設計模式,只有一個工廠,每次增加新類,都需要修改SimpleFactory的代碼,不能對工廠的創建方式進行分類管理,全部都由一個工廠制作。工廠方法,可以對工廠進行擴展,也就是可以對Pizza類分類管理,可以由不同的工廠去創建,更加靈活。

這個好比,簡單工廠只有可以看成商店只有一家供應商,需要什么樣子的產品,直接給工廠說,工廠如果沒有的話要不然制造出來對象,要不然告訴供應商,我不能創建。工廠方法可以看成商店有多個供應商,需要的產品,可以有多重選擇。

下面給出工廠方法的測試代碼:

PizzaStore store = new NYPizzaStore();
store.OrderPizza("Greek");
store.OrderPizza("Cheese");

store = new ChicagoPizzaStore();
store.OrderPizza("Greek");
store.OrderPizza("Cheese");

抽象工廠模式

抽象工廠模式的定義:抽象工廠模式提供了一個接口,用於創建相關或依賴對象的家族,而不需要明確指定具體的類。

定義感覺還真有些抽象,下面就把他易於理解化。

抽象工廠允許客戶使用抽象的接口來創建一組相關的產品,而不需要知道實際的具體產品是什么。這樣客戶就從具體的產品中被解耦了。

下面就來看個關於南北方飲食的差異:

主食分別是北方風味和南方風味。無論是南方味道還是北方味道,其都包括主食和調料:北方主要是以面食和辣椒為主,南方主要是以大米和糖為主。

下面就使用抽象工廠來抽象兩個接口,分別是主食和調料,對應還有兩種風味。

image

接下來是調料和事務的對應實現:

image

接下來看看其聯系

image

在上圖中,AbstractFactory接口定義了兩個方法來分別獲得調料和主食。下面的南北風味是可以看出其具體實現。

這樣就可以在前台查看風味的主食和調料就不用關心具體的實現。直接調用其Create方法就行了。

測試代碼:

class Program
   {
       static void Main(string[] args)
       {
           Console.WriteLine("南方風味:");
           AbstractFactory factory = new SouthFood();
           Food food = factory.CreateFood();
           Console.WriteLine(food.Name);
           Condiment condiment = factory.CreateCondiment();
           Console.WriteLine(condiment.Name);


           Console.WriteLine("北方風味:");
           AbstractFactory factory2 = new NouthFood();
           Food food2 = factory2.CreateFood();
           Console.WriteLine(food2.Name);
           Condiment condiment2 = factory2.CreateCondiment();
           Console.WriteLine(condiment2.Name);
           Console.ReadKey();
       }
   }

從該實例,可以看出抽象工廠是定義了多類產品。工廠方法是一個對象有多種做法,所以在抽象工廠中可以使用多個工廠方法。如果理解了工廠方法,那么抽象工廠應該更好理解些。

抽象工廠是單個接口定義了多個方法,所以具體的工廠肯定都要實現創建方法。

源碼

FactoryPattern.zip


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM