1. 程式人生 > >設計模式(二) 工廠方法模式

設計模式(二) 工廠方法模式

關閉 做的 vat aid 降價 mys 四川 運營 維護


layout: post title: 設計模式(二) 工廠方法模式 tags:

  • Design_Patterns categories:
  • Design_Patterns description: 使用了簡單工廠方法的火鍋店運行穩定 但是也是存在問題的 因為客人越來越挑剔 需要更多的口味 每次在火鍋工廠機器上新添加一個種類的火鍋 我都需要請到小王 讓他來拆開機器 添加新的材料 如 刀頭 什麽的 因為切竹鼠用的刀和切螃蟹的刀是不一樣的 然後還得編程序 總之很麻煩 而且每次弄完之後 我還得請小王吃個飯喝個酒什麽的.....

設計模式(二) 工廠方法模式

1. 股東加入

使用了簡單工廠方法的火鍋店運行穩定 但是也是存在問題的 因為客人越來越挑剔 需要更多的口味 每次在火鍋工廠機器上新添加一個種類的火鍋 我都需要請到小王 讓他來拆開機器 添加新的材料 如 刀頭 什麽的 因為切竹鼠用的刀和切螃蟹的刀是不一樣的 然後還得編程序 總之很麻煩 而且每次弄完之後 我還得請小王吃個飯喝個酒什麽的.....

雖然麻煩點 但是就最近的狀況來看 我的火鍋工廠明顯不能勝任了

由於火鍋店生意很好 也得到了幾個股東的投資 並且決定開設分店 四川的分店 江西的分店 廣東的分店.....開設分店的計劃推上日程 我這邊的火鍋工廠必須做出改變 我已經受夠了 每次拆開機器 添加工具...........受夠了這些繁瑣的操作 而且讓客人在牛肉火鍋中吃出海鮮的味道 確實也不妥

簡單工廠的缺點

很明顯簡單工廠是存在不足的 而且開分店需要迎合當地消費者的口味推出不同地方口味的火鍋 也就是添加了新邏輯 比如四川愛吃麻辣 江西愛吃純辣 廣東不愛辣....... 大公司都是這麽做的 比如肯德基 美國人飲食不健康愛吃肉 中國人飲食健康愛吃蔬菜而且不暴飲暴食 所以以同樣的價格 我們能買到更健康的漢堡 再比如聯想 為了發展中國品牌打入美國市場 采取降價策略..........

如果我的火鍋工廠不作出改變的話 他將會是這樣:

public class HuoguoFactory{
	private String factoryName;
  public Huoguo createHuoguo(String name){	//拿到火鍋的方法
    Huoguo huoguo = null;
    if(factoryName.equals("sichuan")){
    	if(name.equals("sichuanBeffHuoguo")){
      	 huoguo = new BeffHuoguo();
    	}else if(name.equals("sichuanLambHuoguo")){
     	  huoguo = new LambHuoguo();
    	}else if(name.equals("sichuanBambooRatHuoguo")){
      	 huoguo = new BambooRatHuoguo();
    	}
    }
    
    if(factoryName.equals("jiangxi")){
    	if(name.equals("jiangxiBeffHuoguo")){
      	 huoguo = new BeffHuoguo();
    	}else if(name.equals("jiangxiLambHuoguo")){
     	  huoguo = new LambHuoguo();
    	}else if(name.equals("jiangxiBambooRatHuoguo")){
      	 huoguo = new BambooRatHuoguo();
    	}
    }
    ......
    return huoguo;
  }
  HuoguoFactory(String factoryName){
  	this.factoryName=factoryName;
  }
}

如果火鍋的種類很多,所有的判斷都在工廠對象中 業務代碼會很多很多 難以管理 耦合高 而且每次增加 刪除 修改等操作都需要打開工廠 違反了設計準則五:類應該對擴展開放,對修改關閉

所以我們必須引入新方法

2. 工廠方法模式

標準的官方解釋:

? 定義了一個創建對象的接口,但由子類決定實例化的類是哪一個類,工廠方法讓類把實例推移到了子類

說這麽多簡單點解釋就是 以前的火鍋工廠太耦合了 事情太多了 為了對它進行解耦合 將他抽離出來

流程圖如下: 按道理我們的需要將MyStore抽離出來的 但是由於他們只是地點不一樣 其他的都是一樣的 所以我們用同一個類 菱形為接口

graph RL; shop[MyStore<br/>1.優秀的管理方法]; Factory{Factory}; Factory-->shop; id[BeefHuoguoFactory]-.實現.->Factory; id1[LambHuoguoFactory]-.實現.->Factory; id2[BambooRatHuoguoFactory]-.實現.->Factory; id3[.....Factory]-.實現.->Factory; abstract((Huoguo<br/>1.加油方法<br/>2.加調料方法<br/>3.加熱方法)) abstract-.繼承.-idq[BeefHuoguo]; abstract-.繼承.-idq1[LambHuoguo]; abstract-.繼承.-idq2[BambooRatHuoguo]; abstract-.繼承.-idq3[.....]; idq--創建-->id; idq1--創建-->id1; idq2--創建-->id2; idq3--創建-->id3;

這就是工廠方法模式了 為了實現火鍋工廠的解耦合 我就為每一個火鍋類創建一個火鍋工廠 現在畢竟有大股東的加入財大氣粗 有變化 就變化對應的工廠類或火鍋類就可以了 邏輯就被分離出去了 分離到哪裏去了呢? 分離到使用者了 你需要那種產品就選擇那種工廠就好了

不同的觀點 平行的類層級:

怎麽平行了? 這樣看不就平行了嗎

graph RL; Factory{Factory}; id[BeefHuoguoFactory]-.實現.->Factory; id1[LambHuoguoFactory]-.實現.->Factory; id2[BambooRatHuoguoFactory]-.實現.->Factory; id3[.....Factory]-.實現.->Factory; abstract((Huoguo<br/>1.加油方法<br/>2.加調料方法<br/>3.加熱方法)) idq[BeefHuoguo]-.繼承.-abstract; idq1[LambHuoguo]-.繼承.-abstract; idq2[BambooRatHuoguo]-.繼承.-abstract; idq3[.....]-.繼承.-abstract;

是不是兩個平行的類層級?

產品類對應創建者工廠類;

3. 回到我的火鍋帝國

思想有了 現在怎麽運用思想到實際中來? 我們需要分析變化

將所有的火鍋產品都運用一個工廠類 明顯是不實際的 因為不光涉及菜品種類 還涉及口味

分析一下 菜品種類需要變動嗎? 經過我們股東的討論認為 不需要太多變動了 畢竟火鍋店已經運營了有一會了 而且連竹鼠火鍋都推出了 還會有比這個還刁鉆的嗎?

所以我們主要的變化還是在不同地域的口味上 四川愛吃麻 江西喜歡純辣 廣東以清湯涮為主......這是變化

而且我們需要把工廠放進店面(店面成為工廠實體類或者內部維護一個對應的工廠實體類)

至於邏輯部分 也就是客人選擇那種地域口味的火鍋 這層邏輯 我們完全的交給客人了 我們可不提供配送服務 比如長沙的小夥想帶小姑涼吃到正宗的江西火鍋 不好意思 請來到我們南昌總店來品嘗

現在的邏輯圖如下:

graph RL; shop[MyStore<br/>1.優秀的管理方法]; id[JiangxiStore<br/>HuoGuo<br/>1.純辣的操作方法]-->shop; id2[HuNanStore<br/>HuoGuo<br/>1.麻辣的操作方法]-->shop; id3[GuangDongStore<br/>HuoGuo<br/>1.清湯的操作方法]-->shop; abstract((Huoguo<br/>1.加油方法<br/>2.加調料方法<br/>3.加熱方法)) idq[BeefHuoguo]-.繼承.-abstract; idq1[LambHuoguo]-.繼承.-abstract; idq2[BambooRatHuoguo]-.繼承.-abstract; idq3[.....]-.繼承.-abstract; abstract1((Huoguo<br/>1.加油方法<br/>2.加調料方法<br/>3.加熱方法)) idqq[BeefHuoguo]-.繼承.-abstract1; idqq1[LambHuoguo]-.繼承.-abstract1; idqq2[BambooRatHuoguo]-.繼承.-abstract1; idqq3[.....]-.繼承.-abstract1; abstract2((Huoguo<br/>1.加油方法<br/>2.加調料方法<br/>3.加熱方法)) idqqq[BeefHuoguo]-.繼承.-abstract2; idqqq1[LambHuoguo]-.繼承.-abstract2; idqqq2[BambooRatHuoguo]-.繼承.-abstract2; idqqq3[.....]-.繼承.-abstract2; abstract-->id; abstract1-->id2; abstract2-->id3;

這就是我的火鍋帝國繼承體系

4. 總結

由於分離了工廠,當有不同的產品時需要建不同的工廠,將一部分邏輯移到客戶端,體現了創建和選擇的分離 如果有變化只需要修改工廠實體類,或者修改客戶端,解決了簡單工廠的開閉問題;

5. 多談一下 依賴倒置原則

要依賴抽象,不要依賴具體類 就是 程序要依賴於抽象接口,不要依賴於具體實現

如果依賴具體實現 上層調用下層,上層依賴於下層 一旦改變一部分 對應的其他層必須要改變 那我分層幹哈 ? ?

如果我的火鍋店都直接依賴所有的火鍋類 那我的火鍋店中將有很多new火鍋方法 如果有一天 火鍋被實錘了 有害健康(其實已經被錘爛了) 我轉手不幹火鍋生意了 改去做泡泡魚

如果直接依賴火鍋類 那我就需要改店面代碼 如果龐大的話還不如重新開發

如果直接依賴抽象的話 改下傳入的抽象類型就可以了 改下方法就可以了 (方法是肯定要改的 畢竟泡泡魚和火鍋做法不同)

倒置

至於倒置怎麽個倒置? 說說我的理解吧

照我例子 從高層組件開始思考也就是火鍋店 我怎麽構建我的體系?? 我首先需要想 火鍋店的管理 再到 火鍋的制作 需要容器 需要加油 加作料 需要加熱 攪拌 還得為不同的地方設計不同的口味 四川火鍋這樣new 江西火鍋要多加辣 ...…..從高層組件(火鍋店類)想到底層組件(火鍋類) 思路順置了吧

倒置下思路 不從火鍋店開始 先從火鍋開始 從火鍋的抽象開始 火鍋相同的地方設計成一個抽象類 沒有就設計成一個接口.....然後他的子類.....好了 火鍋的設計過程我心裏大致有數了 抽象出了火鍋 我現在開始設計我的火鍋店了 怎麽管理......而且無論用那種工廠 都是在運用火鍋的抽象 不用再去理會火鍋類了 思想從底層到高層了吧 而且依賴的是抽象 不是具體類

設計模式(二) 工廠方法模式