十一回了趟老家,十一前工作一大堆忙成了狗,十一回來后又積累了一大堆又 忙成了狗,今天剛好抽了一點空開始寫工廠方法模式
我看了《Head First 設計模式》P109--P133 這25頁,講述了我們為什么要用工廠模式,里面用做pizza的例子講的特別細膩。看完了就能很清楚的知道為什么要用工廠模式。
年齡越大越不喜歡一知半解,深刻的了解某些未知的事或物以后,它再出現就不怕了
#'New'有什么不對勁?
在技術上,new沒有錯,這是語言的基礎部分。真正的犯人是我們的老朋友 ‘改變’, 以及它是如何影響new使用的。
如果代碼是通過接口而寫,通過多態,可以與任何新類實現該接口。
但是當代碼使用大量的具體類時,那就麻煩了,因為一旦加入新的具體類,就必須改變代碼。意思是代碼沒 " 對修改關閉"。想用新的具體類來擴展代碼,必須重新打開它。
這可咋辦? 只能改代碼
很明顯,如果實例化某些具體類,將使orderPizza()出問題,沒辦法讓orderPizza()對修改關閉,
但是咱們還是能很明顯的看出哪些會變,哪些不會變,這個時候就可以考慮封裝了,
上面這些引出了下面的簡單工廠模式
#簡單工廠模式
1)算是定義吧
簡單工廠模式其實並不是一個模設計模式,反而比較像一種編程習慣,還請不要把這個習慣認為是“工廠模式”。
不要因為簡單工廠不是一個真正的模式,就忽略它的用法。
2)類圖
3)舉個例子(java)
public class PizzaStore { SimplePizzaFactory factory; public PizzaStore(SimplePizzaFactory factory){ this.factory=factory; } public Pizza orderPizza(String type){ Pizza pizza; pizza=factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } } ############################ public class SimplePizzaFactory { public Pizza createPizza(String type){ Pizza pizza=null; if(type.equals("cheese")){ pizza=new CheesePizza(); }else if (type.equals("greek")){ pizza=new GreekPizza(); }else if(type.equals("pepperoni")){ pizza=new PepperoniPizza(); }else if (type.equals("clam")){ pizza=new ClamPizza(); }else if (type.equals("veggie")){ pizza=new VeggiePizza(); } return pizza; } } ######################################################## public abstract class Pizza { String name; String dough; String sauce; void prepare(){ System.out.print("Preparing"); }; void bake(){ System.out.print("Baking"); }; void cut(){ System.out.print("cut"); }; void box(){ System.out.print("box"); }; } public class VeggiePizza extends Pizza{ } public class ClamPizza extends Pizza { } public class PepperoniPizza extends Pizza { } public class PepperoniPizza extends Pizza { } ################################# public static void main(String[] args) { PizzaStore store=new PizzaStore(); Pizza pizza=store.orderPizza("cheese"); System.out.println("eat Pizza"); }
4)舉個例子(python)
#工廠方法模式
#引入
#匹薩生意火爆,現在有很多人要開加盟店,不同地區的加盟店口味有差異。PizzaStore有個不錯的訂單系統,希望所有加盟店對訂單的處理一致。
各區域匹薩店之間的差異在於他們制作匹薩的風味(比如 NYStyle 餅薄, ChicagoStyle 餅厚等),我們現在讓createPizza()來應對這些變化負責創建正確種類的匹薩。
做法是讓PizzaStore的各個子類負責定義自己的createPizza()方法。所以我們會得到PizzaStore的具體類。
#定義
定義了一個創建對象的接口,但有子類決定要實例化的類是哪一個。工廠方法讓類把實例化推遲到子類。
所有工廠模式都是用來封裝對象的創建。工廠方法模式(Factory Method Pattern) 通過讓子類決定該創建的對象是什么,來達到對象創建的過程封裝的目的。
原本是由一個對象負責所有具體的實例化,現在變成一群子類負責實例化
#類圖
#舉個例子(java)
public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza; pizza=createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } abstract Pizza createPizza(String type); } ########################################################### public class NYPizzaStore extends PizzaStore{ Pizza createPizza(String item){ if(item.equals("cheese")){ return new NYStyleCheesePizza(); }else if (item.equals("greek")){ return new NYStyleGreekPizza(); }else if(item.equals("pepperoni")){ return new NYStylePepperoniPizza(); }else if (item.equals("clam")){ return new NYStyleClamPizza(); }else if (item.equals("veggie")){ return new NYStyleVeggiePizza(); }else return null } ######## public class ChicagoPizzaStore extends PizzaStore { Pizza createPizza(String item){ if(item.equals("cheese")){ return new ChicagoStyleCheesePizza(); }else if (item.equals("greek")){ return new ChicagoStyleGreekPizza(); }else if(item.equals("pepperoni")){ return new ChicagoStylePepperoniPizza(); }else if (item.equals("clam")){ return new ChicagoStyleClamPizza(); }else if (item.equals("veggie")){ return new ChicagoStyleVeggiePizza(); }else return null; } } ########################################################## public abstract class Pizza { String name; String dough; String sauce; void prepare(){ } void bake(){ } void cut(){ } void box(){ } } ############## public class NYStyleCheesePizza extends Pizza { public NYStyleCheesePizza(){ name="NY Style Sauce and Cheese Pizza"; dough="Thin Crust Dough"; sauce="Marinara Sauce"; } } ######## public class NYStyleClamPizza extends Pizza { } ###### public class NYStyleGreekPizza extends Pizza{ } #### public class NYStylePepperoniPizza extends Pizza { } ####### public class NYStyleVeggiePizza extends Pizza { } ######### public class ChicagoStyleCheesePizza extends Pizza { public ChicagoStyleCheesePizza(){ name="Chicago Style Sauce and Cheese Pizza"; dough="Thick Crust Dough"; sauce="Plum Tomato Sauce"; } } ######### public class ChicagoStyleGreekPizza extends Pizza{ } ######## public class ChicagoStylePepperoniPizza extends Pizza { } ####### public class ChicagoStyleClamPizza extends Pizza{ } ###### public class ChicagoStyleVeggiePizza extends Pizza { } ##################################################################### public class javatest1 { public static void main(String[] args) throws IOException,ClassNotFoundException{ PizzaStore nyStore=new NYPizzaStore(); PizzaStore chicagoStore=new ChicagoPizzaStore(); Pizza pizza=nyStore.orderPizza("cheese"); System.out.println("eat NYStylePizza"); pizza = chicagoStore.orderPizza("cheese"); System.out.println("eat ChicagoStylePizza"); } }
#舉個例子(python)
class Person(object): def __init__(self,name): self.name = name def work(self): print(self.name+"工作開始了") axe = Stone_Factory().create_axe() axe.cut_tree() class Axe(object): def __init__(self,name): self.name = name def cut_tree(self): print("使用%s斧頭砍樹"%self.name) class StoneAxe(Axe): def cut_tree(self): print("使用石斧頭砍樹") class SteelAxe(Axe): def cut_tree(self): print("使用鐵斧頭砍樹") class Tree(object): pass #工廠類 ''' class Factory(object): @staticmethod def create_axe(type): if type == "stone": return StoneAxe("花崗岩斧頭") if type == "steel": return SteelAxe("鐵斧頭") ''' class Factory(object): def create_axe(self): pass class Stone_Factory(Factory): def create_axe(self): return StoneAxe("花崗岩斧頭") class Steel_Factory(Factory): def create_axe(self): return SteelAxe("鐵斧頭")
code來自https://blog.csdn.net/Mr_Quiet/article/details/80998337
#抽象工廠模式
#引入
紐約匹薩店生意火爆,越來越好,需要開好多家紐約披薩店,芝加哥也是面臨同樣的情況。為了保證質量,就得控制原料。所以我們得建造原料工廠,來生產不同區域的原料。
#定義
抽象工廠模式提供一個接口,用於創建相關或依賴對象的家族,而不需要明確指定具體類。
允許客戶用抽象的借口創建一組產品,不需要知道實際產出的具體產品是什么,這樣客戶就從具體的產品解耦了。
#結構圖
#使用場景
)客戶端不依賴於產品類實例如何被創建、實現等細節
)強調一系列相關的產品對象(屬於統一產品族)一起使用創建對象需要大量重復的代碼
)提供一個產品類的庫,所以的產品以同樣或者大部分相同的接口出現,從而使客戶端不依賴具體實現
#優點
實現解耦
#缺點
)規定了所有可能被創建的產品集合,產品族擴展新的產品困難,需要修改抽象工廠的接口
)增加了系統的抽象性和理解難度
#舉個例子(java)
public interface Cheese { } ############# public interface Pepperoni { } ########## public interface Sauce { } ################## public interface Clams { } public class BlackOlives implements Veggies { } ######### public interface Dough { } ########## public interface Veggies { } ###################################################################### public class MozzarellaCheese implements Cheese{ } ######## public class ReggianoCheese implements Cheese { } ##### public class Eggplant implements Veggies { } ##### public class Garlic implements Veggies{ } ####### public class Mushroom implements Veggies { } ########### public class RedPepper implements Veggies{ } ######## public class Spinach implements Veggies{ } ##### public class FreshClams implements Clams{ } ###### public class FrozenClams implements Clams{ } ####### public class MarinaraSauce implements Sauce { } ######### public class PlumTomatoSauce implements Sauce { } ######## public class SlicedPepperoni implements Pepperoni{ } ######### public class SlicePepperoni implements Pepperoni{ } ######## public class ThinCrustDough implements Dough { } ######## public class ThickCrustDough implements Dough { } ######################################################## public interface PizzaIngredientFactory { public Sauce createSauce(); public Cheese createCheese(); public Veggies[] createVeggies(); public Pepperoni createPepperoni(); public Clams createClam(); public Dough createDough(); } ################### public class NYPizzaIngredientFactory implements PizzaIngredientFactory { public Dough createDough(){ return new ThinCrustDough(); } public Sauce createSauce(){ return new MarinaraSauce(); } public Cheese createCheese(){ return new ReggianoCheese(); } public Veggies[] createVeggies(){ Veggies veggies[]={new Garlic(),new Mushroom(),new RedPepper()}; return veggies; } public Pepperoni createPepperoni(){ return new SlicePepperoni(); } public Clams createClam(){ return new FreshClams(); } } ######### public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory { public Dough createDough(){ return new ThickCrustDough(); } public Sauce createSauce(){ return new PlumTomatoSauce(); } public Cheese createCheese(){ return new MozzarellaCheese(); } public Veggies[] createVeggies(){ Veggies veggies[]={new BlackOlives(),new Spinach(),new Eggplant()}; return veggies; } public Pepperoni createPepperoni(){ return new SlicedPepperoni(); } public Clams createClam(){ return new FrozenClams(); } } ####### ############################################### public abstract class Pizza { String name; Dough dough; Sauce sauce; Veggies veggies[]; Cheese cheese; Pepperoni pepperoni; Clams clam; abstract void prepare(); void bake(){ System.out.print("Baking"); }; void cut(){ System.out.print("cut"); }; void box(){ System.out.print("box"); }; void setName(String name){ this.name=name; } String getName(){ return name; } public String toString(){ return name; } } ############### public class CheesePizza extends Pizza{ PizzaIngredientFactory ingreditentFactory; public CheesePizza(PizzaIngredientFactory ingredientFactory){ this.ingreditentFactory=ingredientFactory; } void prepare(){ System.out.print("Preparing"+name); dough=ingreditentFactory.createDough(); sauce=ingreditentFactory.createSauce(); cheese=ingreditentFactory.createCheese(); } } ############# public class ClamPizza extends Pizza { PizzaIngredientFactory ingredientFactory; public ClamPizza(PizzaIngredientFactory ingredientFactory){ this.ingredientFactory=ingredientFactory; } void prepare(){ System.out.print("Preparing"+name); dough=ingredientFactory.createDough(); sauce=ingredientFactory.createSauce(); clam=ingredientFactory.createClam(); } } ###################### public class PepperoniPizza extends Pizza { PizzaIngredientFactory ingreditentFactory; public PepperoniPizza(PizzaIngredientFactory ingredientFactory){ this.ingreditentFactory=ingredientFactory; } void prepare(){ System.out.print("Preparing"+name); dough=ingreditentFactory.createDough(); sauce=ingreditentFactory.createSauce(); cheese=ingreditentFactory.createCheese(); } } ################ public class VeggiePizza extends Pizza { PizzaIngredientFactory ingreditentFactory; public VeggiePizza(PizzaIngredientFactory ingredientFactory){ this.ingreditentFactory=ingredientFactory; } void prepare(){ System.out.print("Preparing"+name); dough=ingreditentFactory.createDough(); sauce=ingreditentFactory.createSauce(); cheese=ingreditentFactory.createCheese(); } } ############################################################################################### public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza; pizza=createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } abstract Pizza createPizza(String type); } ############################ public class NYPizzaStore extends PizzaStore{ protected Pizza createPizza(String item){ Pizza pizza=null; PizzaIngredientFactory nyIngredientFactory=new NYPizzaIngredientFactory(); if(item.equals("cheese")){ pizza=new CheesePizza(nyIngredientFactory); pizza.setName("New York Style Cheese Pizza"); }else if(item.equals("veggie")){ pizza=new VeggiePizza(nyIngredientFactory); pizza.setName("New York Style Veggie Pizza"); }else if(item.equals("clam")){ pizza=new ClamPizza(nyIngredientFactory); pizza.setName("New York Style Clam Pizza"); }else if(item.equals("pepperoni")){ pizza=new PepperoniPizza(nyIngredientFactory); pizza.setName("New York Style Pepperoni Pizza"); } return pizza; } } ################### public class ChicagoPizzaStore extends PizzaStore{ protected Pizza createPizza(String item){ Pizza pizza=null; PizzaIngredientFactory nyIngredientFactory=new ChicagoPizzaIngredientFactory(); if(item.equals("cheese")){ pizza=new CheesePizza(nyIngredientFactory); pizza.setName("New York Style Cheese Pizza"); }else if(item.equals("veggie")){ pizza=new VeggiePizza(nyIngredientFactory); pizza.setName("New York Style Veggie Pizza"); }else if(item.equals("clam")){ pizza=new ClamPizza(nyIngredientFactory); pizza.setName("New York Style Clam Pizza"); }else if(item.equals("pepperoni")){ pizza=new PepperoniPizza(nyIngredientFactory); pizza.setName("New York Style Pepperoni Pizza"); } return pizza; } } ########################################################################### public class javatest1 { public static void main(String[] args) throws IOException,ClassNotFoundException{ PizzaStore nyPizzaStore=new NYPizzaStore(); nyPizzaStore.orderPizza("cheese"); System.out.print("\n"); PizzaStore chicagoPizzaStore=new ChicagoPizzaStore(); chicagoPizzaStore.orderPizza("clam"); } }
#舉個例子(python)
#!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = 'Andy' """ 大話設計模式 設計模式——抽象工廠模式 抽象工廠模式(Abstract Factory Pattern):提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們的類 """ import sys #抽象用戶表類 class User(object): def get_user(self): pass def insert_user(self): pass #抽象部門表類 class Department(object): def get_department(self): pass def insert_department(self): pass #操作具體User數據庫類-Mysql class MysqlUser(User): def get_user(self): print 'MysqlUser get User' def insert_user(self): print 'MysqlUser insert User' #操作具體Department數據庫類-Mysql class MysqlDepartment(Department): def get_department(self): print 'MysqlDepartment get department' def insert_department(self): print 'MysqlDepartment insert department' #操作具體User數據庫-Orcal class OrcaleUser(User): def get_user(self): print 'OrcalUser get User' def insert_user(self): print 'OrcalUser insert User' #操作具體Department數據庫類-Orcal class OrcaleDepartment(Department): def get_department(self): print 'OrcalDepartment get department' def insert_department(self): print 'OrcalDepartment insert department' #抽象工廠類 class AbstractFactory(object): def create_user(self): pass def create_department(self): pass class MysqlFactory(AbstractFactory): def create_user(self): return MysqlUser() def create_department(self): return MysqlDepartment() class OrcaleFactory(AbstractFactory): def create_user(self): return OrcalUser() def create_department(self): return OrcalDepartment() if __name__ == "__main__": db = sys.argv[1] myfactory = '' if db == 'Mysql': myfactory = MysqlFactory() elif db == 'Orcal': myfactory = OrcaleFactory() else: print "不支持的數據庫類型" exit(0) user = myfactory.create_user() department = myfactory.create_department() user.insert_user() user.get_user() department.insert_department() department.get_department()
代碼來自https://www.cnblogs.com/onepiece-andy/p/python-abstract-factory-pattern.html
#工廠方法模式與抽象工廠模式對比
)都是負責創建對象,工廠方法模式 用的方法是通過繼承,抽象工廠模式 用的方法是對象的組合
)工廠方法模式 通過子類來創建對象,客戶只需要知道所使用的抽象類型,右子類來負責決定具體類型。換句話說 工廠方法模式只負責將客戶從具體類型中解耦。
)抽象工廠模式 用來創建一個產品家族的抽象類型,也可以把客戶從所使用的具體產品中解耦。可以把一組相關的產品集合起來。
如果需要擴展這組相關產品,就必須改變接口,這是抽象工廠的缺點。工廠方法模式只涉及一個產品。
)抽象工廠模式經常使用工廠方法模式來實現它(抽象工廠模式)的具體工廠,純粹是用來創建產品。
參考
《Head First設計模式》
https://blog.csdn.net/qq_28859325/article/details/60580578
https://www.jianshu.com/p/610a26d9d958