設計模式學習筆記之工廠模式

2021-09-12 01:39:09 字數 4424 閱讀 4812

本文講述乙個披薩的誕生

我有一家披薩店,顧客來點了想吃的品種,然後我要準備材料、烘烤、剪下、幫顧客打包。這個過程用**怎麼實現呢?

首先定義好準備、烘烤、剪下和打包這些動作

public

abstract

class

pizza

public

void

cut()

public

void

box()

public

void

setname

(string name)

}複製**

然後定義一下都可以做哪些披薩種類

public

class

cheesepizza

extend

pizza

}複製**

public

class

greekpizza

extends

pizza

}複製**

準備工作做完,就等著顧客來點餐了

public

class

orderpizza

else

if ("cheese".equals(type))else

pizza.prepare();

pizza.bake();

pizza.cut();

pizza.box();

}while (true);

}private string gettype

() catch (ioexception e)

return type;

}}複製**

整個過程如下:

顧客根據披薩的種類進行點餐,然後根據型別進行建立披薩物件,進行準備、烘焙、剪下、打包

很明顯,這樣設計是有問題的。如果店裡有了新品,或者下架某種類披薩,就要修改orderpizza類中根據顧客輸入來建立物件這段**,顯然是違背上文提到的開放封閉原則。如下**,現在我們已經知道哪些會改變,哪些不會改變,是時候使用封裝了。

//需要修改

if ("greek".equals(type))else

//不需要修改

pizza.prepare();

pizza.bake();

pizza.cut();

pizza.box();

複製**

現在最好將建立物件移到orderpizza()之外,但怎麼做呢?我們可以把建立披薩的**移到另乙個物件中,由這個新物件專職建立披薩。 我們稱這個新物件為「工廠」。

工廠(factory)處理建立物件的細節。一旦有了******pizzafactory,orderpizza()就變成此物件的客戶。當需要披薩時,就叫披薩工廠做乙個。那些orderpizza()方法需要知道希臘披薩或者蛤蜊披薩的日子一去不復返了。現在orderpizza()方法只關心從工廠得到了乙個披薩,而這個披薩實現了pizza介面,所以它可以呼叫prepare()、bake()、cut()、box()來分別進行準備、烘烤、切片、裝盒。

******pizzafactory是我們的新類,它負責為客戶建立披薩

public

class

******factorypizza

else

if ("cheese".equals(type)) else

if ("beef".equals(type))

return pizza;

}}複製**

新的order只需構造時傳入乙個工廠,然後帶入訂單型別來使用工廠建立披薩,代替之前具體的例項化

public

class

orderpizza

pizza orderpizza

(string type)

return pizza;

}}複製**

雖然看似**同傳統方式一樣,但是我們已經將變化的**抽取出來了,在orderpizza中我們無需再次修改,此時我們已經將變化的和不變化的隔離開來了。

如果披薩店生意越來越好,考慮開幾家加盟店。身為加盟公司的經營者,你希望確保加盟店的運營質量,還希望各地的披薩有自己不同的區域特點。在推廣******factorypizza時,發現加盟店採用的統一的工廠建立的披薩,但是其他部分卻開始採用自創的流程,比如烘烤方式,包裝方式等等。那麼如果建立乙個框架,約束關鍵步驟的同時又能保持一定的彈性呢?

有乙個辦法可以讓披薩製作活動侷限於orderpizza類,同時讓不同的店還擁有自己的特色。

所要做的事情就是把createpizza()方法放回到orderpizza中,不過得將它設定成抽象方法,然後為每個店鋪建立乙個orderpizza的子類。 來看下修改後的orderpizza:

public

abstract

class

orderpizza

//建立工廠方法改為抽象的,方便子類修改

abstract pizza createpizza

(string type);}

複製**

現在已經有乙個orderpizza作為父類,讓不同區域的店鋪來繼承orderpizza,每個子類各自決定製作什麼風味的披薩。

orderpizza已經有乙個不錯的訂單系統,由orderpizza()負責處理訂單,而你希望所有加盟店對於訂單的處理都能一致。 各個區域披薩店之間的差異在於他們製作披薩的風味(紐約披薩的薄脆、芝加哥披薩的餅厚等),我們現在要讓現在createpizza()能夠應對這些變化來負責建立正確種類的披薩。做法是讓orderpizza的各個子類負責定義自己的createpizza()方法。所以我們會得到一些orderpizza具體的子類,每個子類都有自己的披薩變體,而仍然適合orderpizza框架,並使用除錯好的orderpizza()方法。

// 如果加盟店為顧客提供紐約風味的披薩,就使用nystyleorderpizza,

// 因為此類的createpizza()方法會建立紐約風味的披薩

public

class

nystyleorderpizza

extends

orderpizza

else

if (type.equals("veggie"))

return pizza;

}} // 類似的,利用芝加哥子類,我們得到了帶芝加哥原料的createpizza()實現

public

class

chicagostyleorderpizza

extends

orderpizza

else

if (type.equals("veggie"))

return pizza;

}}複製**

現在問題來了,orderpizza的子類終究只是子類,如何能夠做決定?在nystyleorderpizza類中,並沒有看到任何做決定邏輯的**。 關於這個方面,要從orderpizza類的orderpizza()方法觀點來看,此方法在抽象的orderpizza內定義,但是只在子類中實現具體型別。 orderpizza()方法對物件做了許多事情(例如:準備、烘烤、切片、裝盒),但由於pizza物件是抽象的,orderpizza()並不知道哪些實際的具體類參與進來了。換句話說,這就是解耦(decouple)! 當orderpizza()呼叫createpizza()時,某個披薩店子類將負責建立披薩。做哪一種披薩呢?當然是由具體的披薩店決定。 那麼,子類是實時做出這樣的決定嗎?不是,但從orderpizza()的角度看,如果選擇在nystyleorderpizza訂購披薩,就是由這個子類(nystyleorderpizza)決定。嚴格來說,並非由這個子類實際做「決定」,而是由「顧客」決定哪一家風味的披薩店才決定了披薩的風味。

我們來看下如何呼叫:

public

class

test

}複製**

執行結果如下:

preparing nystylecheesepizza baking;

preparing nystylecheesepizza cutting;

preparing nystylecheesepizza boxing;

-------

preparing nystyleveggiepizza baking;

preparing nystyleveggiepizza cutting;

preparing nystyleveggiepizza boxing;

複製**

設計模式學習系列:

基本概念

裝飾者模式

設計模式學習筆記之簡單工廠模式

所謂簡單工廠模式,即提供建立物件的介面,而具體建立什麼物件,由客戶端決定。比如,我們有ibird這樣乙個抽象類,有chicken和duck這兩個類實現ibird。那麼,如果我們想靈活的建立chicken或ibird,那麼就需要用到簡單工廠模式。factory根據接收到的字串,決定返回的物件。客戶端用...

學習設計模式筆記之工廠模式1

本文系個人的筆記,是總結大神的講解,不是本人原創,重要的事情說三遍。1 工廠方法模式 factory method 工廠方法模式分為三種 1.1 普通工廠模式 就是建立乙個工廠類,對實現了同一介面的一些類進行例項的建立。簡單理解就是將必須用到的方法做成介面,然後需要實現方法的類都去實現這乙個介面,通...

設計模式學習筆記之簡單工廠模式

解耦,此二字時刻牢記在心。雖然我現在還不能透徹地理解這兩個字的含義,但心中能有個大概的概念。如 復用。簡單工廠模式,就是利用繼承和多型來解耦。以 大話設計模式 中此模式的計算器為例,就是先提出乙個運算父類,具體的運算類繼承自該父類。父類中有計算結果的方法,而子類就負責實現父類中計算結果方法的具體實現...