![第9章工厂模式_第1页](http://file2.renrendoc.com/fileroot_temp3/2021-11/6/de3b0d75-b87b-4bd5-983b-bb2a72e89776/de3b0d75-b87b-4bd5-983b-bb2a72e897761.gif)
![第9章工厂模式_第2页](http://file2.renrendoc.com/fileroot_temp3/2021-11/6/de3b0d75-b87b-4bd5-983b-bb2a72e89776/de3b0d75-b87b-4bd5-983b-bb2a72e897762.gif)
![第9章工厂模式_第3页](http://file2.renrendoc.com/fileroot_temp3/2021-11/6/de3b0d75-b87b-4bd5-983b-bb2a72e89776/de3b0d75-b87b-4bd5-983b-bb2a72e897763.gif)
![第9章工厂模式_第4页](http://file2.renrendoc.com/fileroot_temp3/2021-11/6/de3b0d75-b87b-4bd5-983b-bb2a72e89776/de3b0d75-b87b-4bd5-983b-bb2a72e897764.gif)
![第9章工厂模式_第5页](http://file2.renrendoc.com/fileroot_temp3/2021-11/6/de3b0d75-b87b-4bd5-983b-bb2a72e89776/de3b0d75-b87b-4bd5-983b-bb2a72e897765.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1第九章第九章 工厂模式工厂模式new运算符运算符(对象创建对象创建)Duck duck;if (picnic) / 郊游野餐 duck = new MallardDuck( ); else if (hunting) / 打猎 duck = new DecoyDuck( ); else if (inBathTub) / 在浴缸里 duck = new RubberDuck(); 维护升级困难,易于出错。也违背了开闭原开闭原则则。2订购比萨订购比萨Pizza orderPizza() Pizza pizza = new Pizza();pizza.prepare(); / 准备(例如揉面皮、加佐
2、料等)pizza.bake(); / 烘烤pizza.cut(); / 切片pizza.box(); / 装到盒子里return pizza;先要制作一个比萨饼。3需要更多的比萨类型需要更多的比萨类型Pizza orderPizza(String type) Pizza pizza;if (type.equals(cheese) / 奶酪奶酪pizza = new CheesePizza( ); else if (type.equals(“greek”) / 希腊希腊pizza = new GreekPizza( ); else if (type.equals( pepperoni ) / 辣
3、香肠辣香肠pizza = new PepperoniPizza( );pizza.prepare();pizza.cut();pizza.box();return pizza;每个Pizza的子类型都知道怎样准备自己。 4需要更多的比萨类型需要更多的比萨类型( (续续) )Pizza orderPizza(String type) Pizza pizza;if (type.equals(cheese) / 奶酪pizza = new CheesePizza( ); else if (type.equals(“greek”) / 希腊pizza = new GreekPizza( ); else
4、 if (type.equals( pepperoni ) / 辣香肠pizza = new PepperoniPizza( ); else if (type.equals(“clam”) / 蛤蜊pizza = new ClamPizza(); else if (type.equals(“veggie”) / 蔬菜pizza = new VeggiePizza();pizza.prepare();pizza.cut();pizza.box();return pizza;变化的部分不变的部分5Pizza orderPizza(String type) Pizza pizza; pizza.pr
5、epare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza;if (type.equals(Cheese) pizza = new CheesePizza(); else if (type.equals(pepperoni) pizza = new PepperoniPizza(); else if (type.equals(clam) pizza = new ClamPizza(); else if (type.equals(veggie) pizza = new VeggiePizza();这段移到一个专门负责创建比萨的对象里
6、封装对象创建封装对象创建 也许把对象创建代码从orderPizza( )方法中移走是一个好主意。6对象工厂对象工厂 专门负责对象创建的对象,我们给它一个名字,称之为工厂工厂。工厂处理对象创建的细节。如果我们有一个SimplePizzaFactory,orderPizza( )方法就是它的客户客户。当orderPizza( )需要比萨对象时,就要求SimplePizzaFactory创建。7简单比萨工厂简单比萨工厂public class SimplePizzaFactory public Pizza createPizza(String type) Pizza pizza = null;if
7、(type.equals(“cheese”) / 奶酪pizza = new CheesePizza(); 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; 8重做重做PizzaStore类类 public class PizzaStore Si
8、mplePizzaFactory 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; 把new替换成工厂对象的创建方法。这里不再使用具体实例化!9简单工厂定义简单工厂定义 简单工厂实际上不是
9、一个设计模式,更象一种编程风格。新比萨店类图:PizzaStoreSimplePizzaFactorycreatePizza()orderPizza()Pizzaprepare()bake()cut()box()CheesePizzaVeggiePizzaClamPizzaPepperoniPizza工厂客户创建比萨的工厂。唯一用到具体比萨类的地方。抽象的比萨产品。具体的比萨产品。10比萨专营店比萨专营店 不同地区的经销商可能要提供不同风格的比萨(New York,Chicago,California等等)。你要求所有经销商使用你的PizzaStore代码,以便所有比萨按相同的方式准备。NY比
10、萨店制造NY风格比萨:薄壳、可口的沙司及少量的奶酪。Chicago比萨店制造Chicago风格比萨:厚壳、油腻的沙司及较多的奶酪。11一种做法一种做法NYPizzaFactory nyFactory = new NYPizzaFactory();PizzaStore nyStore = new PizzaStore(nyFactory);nyStore.orderPizza(“Veggie”);ChicagoPizzaFactory chicagoFactory = new ChicagoPizzaFactory();PizzaStore chicagoStore = new PizzaSto
11、re(chicagoFactory);chicagoStore.orderPizza(“Veggie”);制造纽约风味的比萨工厂。制造芝加哥风味的比萨工厂。12多一些控制多一些控制 每一个地区有自己的经销店,有自己的生产工厂。这些经销店订购比萨的流程应该是一样的。现在的状况是无法约束各地经销店遵守这些流程。另外,每一个经销店都要建一个对应的生产工厂创建比萨,管理上增加了难度。 能不能创建一个比萨经销店的框架,让各地的经销店强制执行这个框架,又让每个经销店又保留必要的自由度呢?能不能把比萨的创建与经销店捆绑在一起呢? 我们还是来试试。13比萨店框架比萨店框架public abstract cla
12、ss PizzaStore public Pizza orderPizza(String type) Pizza pizza = createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza; abstract Pizza createPizza(String type); / 抽象的方法14允许子类决策允许子类决策不同地区的比萨店制作出的比萨特点是不一样的。createPizza()方法负责创建合适的比萨。我们让PizzaStore子类定义各自的createPizza()方法。所以,我们
13、有许多具体的PizzaStore子类,它们满足PizzaStore的框架,但又有各自的变种。15PizzaStoreNYStypePizzaStorecreatePizza( ) ChicagoStypePizzaStorecreatePizza( )createPizza( )orderPizza( )public Pizza createPizza(type) if (type.equals(Cheese) pizza = new NYStyleCheesePizza(); else if (type.equals(pepperoni) pizza = new NYStylePeppero
14、niPizza(); else if (type.equals(clam) pizza = new NYStyleClamPizza(); else if (type.equals(veggie) pizza = new NYStyleVeggiePizza(); public Pizza createPizza(type) if (type.equals(Cheese) pizza = new ChicagoStyleCheesePizza(); else if (type.equals(pepperoni) pizza = new ChicagoStylePepperoniPizza();
15、 else if (type.equals(clam) pizza = new ChicagoStyleClamPizza(); else if (type.equals(veggie) pizza = new ChicagoStyleVeggiePizza(); 16创建创建PizzaStorepublic class NYPizzaStore extends PizzaStore Pizza createPizza(String item) if (item.equals(cheese) return new NYStyleCheesePizza(); else if (item.equa
16、ls(veggie) return new NYStyleVeggiePizza(); else if (item.equals(clam) return new NYStyleClamPizza(); else if (item.equals(pepperoni) return new NYStylePepperoniPizza(); else return null;17订购比萨订购比萨( (工厂方法工厂方法) ) 实例化一个比萨店。 调用orderPizza()方法,传入需要的比萨类型,如cheese、 veggie等。 调用createPizza()方法创建比萨。NYPizzaStor
17、e实例化一 个NY风格比萨,ChicagoPizzaStore实例化一个Chicago风 格比萨。 orderPizza()方法不知道创建什么比萨,但是,它知道是 一个比萨,并且准备,烘烤,切片及装盒。18Pizza实现实现public abstract class Pizza String name;String dough;String sauce;ArrayList toppings = new ArrayList(); / 佐料可能有多种void prepare() System.out.println(Preparing + name);System.out.println(“Tos
18、sing dough.”); / 搅拌面团System.out.println(“Adding sauce.”); / 添加沙司System.out.println(“Adding toppings: ”); / 添加佐料for (int i = 0; i toppings.size(); i+) System.out.println( + toppings.get(i);19Pizza实现实现(续续) void bake() System.out.println(“Bake for 25 minutes at 350”); / 以摄氏350度烘烤25分钟void cut() System.o
19、ut.println(Cutting the pizza into diagonal slices); void box() System.out.println(Place pizza in official PizzaStore box); public String getName() return name;20Pizza实现实现(续续)public class NYStyleCheesePizza extends Pizza public NYStyleCheesePizza() name = NY Style Sauce and Cheese Pizza;dough = Thin
20、Crust Dough;sauce = “Marinara Sauce”; /番茄大蒜调味汁沙司 toppings.add(Grated Reggiano Cheese);搓碎的Reggiano奶酪21Pizza实现实现(续续)public class ChicagoStyleCheesePizza extends Pizza public ChicagoStyleCheesePizza() name = Chicago Style Deep Dish Cheese Pizza;dough = Extra Thick Crust Dough;sauce = Plum Tomato Sauce;
21、 / 犁形番茄沙司toppings.add(Shredded Mozzarella Cheese);void cut() System.out.println(Cutting the pizza into square slices);切碎的白干酪奶酪覆盖了超类的cut0方法,比萨被切成正方形。芝加哥风格深盘奶酪比萨22测试代码测试代码public class PizzaTestDrive public static void main(String args) PizzaStore nyStore = new NYPizzaStore(); PizzaStore chicagoStore =
22、 new ChicagoPizzaStore(); Pizza pizza = nyStore.orderPizza(cheese); System.out.println(Ethan ordered a + pizza.getName() + n); pizza = chicagoStore.orderPizza(cheese); System.out.println(Joel ordered a + pizza.getName() + n); 23两两个个比比萨萨都都准准备备好好了了:佐佐料料加加上上了了、烘烘焙焙完完成成了了、切切片片装装盒盒了了。超超类类不不管管细细节节。通通过过实实例
23、例化化正正确确的的比比萨萨类类,子子类类自自行行照照料料这这一一切切。测试代码测试代码24会会工厂方法模式会会工厂方法模式 所有工厂模式封装了对象的创建。工厂方法模式封装对象创建的特点:子类决定需要创建的对象。PizzaStorecreatePizza()orderPizza()NYPizzaStorecreatePizza()ChicagoPizzaStorecreatePizza()抽象的创建者createPizza()方法是工厂方法具体的创建者创建者类25PizzaNYStyleCheesePizzaChicagoStyleCheesePizzaNYStylePepperoniPizza
24、NYStyleClamPizzaNYStyleVeggiePizzaChicagoStylePepperoniPizzaChicagoStyleClamPizzaChicagoStyleVeggiePizza具体的产品产品类26工厂方法模式定义工厂方法模式定义工厂方法模式定义了一个创建对象的接口,让子类决定哪一个类实例化。工厂方法让一个类的实例化推迟到子类。27ProductConcreteProductCreatorfactoryMethod()anOperation()ConcreteCreatorfactoryMethod()创建者是一个抽象类,除工厂方法外,包含其它所有操作产品方法的实
25、现。创建者子类必须实现抽象的factoryMethod()。ConcreteCreator具有产品知识,它实现factoryMethod(),负责创建一个或多个具体的产品。工厂方法类图工厂方法类图28PizzaStore直接创建比萨对象,它依赖于所有的比萨对象。如果这些类的实现改变了,就可能要修改PizzaStore。由于比萨类具体实现的任何变化都要影响到PizzaStore,我们说PizzaStore依依赖赖于于比萨的实现。每增加一个新品种比萨,PizzaStore就增加了一个依赖。创建创建 比萨比萨对象,而对象,而不委托到不委托到工厂工厂29依赖倒置原则依赖倒置原则 很显然,减少对具体类的
26、依赖是一个好事情。实际上,我们有一个OO设计原则形式化这个概念:依赖倒置依赖倒置原则原则。设设计计原原则则依赖于抽象,不要依赖于具体类。30依赖倒置原则依赖倒置原则(续续) 这个原则很类似于前面讲到的“要对接口编程,不要对实现编程”的原则。但是,依赖倒置原则是关于抽象的更强的陈述。它暗示:高层组件不要依赖于低层的组件高层组件不要依赖于低层的组件,无论是高层组件,还是低层组件,都应当依赖于抽象。31应用依赖倒置原则应用依赖倒置原则 在前面的PizzaStore依赖图中, PizzaStore 依赖于每一个比萨类型,因为,它实际上在它的orderPizza()方法中实例化了具体类型。 如果我们创建
27、了一个抽象的比萨,我们就不需要创建具体的比萨,避免了抽象之外的附加支持。 我们怎样获得orderPizza()方法中的比萨实例呢?工厂方法。使用工厂方法创建比萨对象(下页):32PizzaStore仅依赖于抽象类PizzaPizza是一个抽象类.一一个个抽抽象象具体的比萨类也依赖于Pizza抽象,因为,它们实现了抽象类Pizza中的接口。33帮助你理解依赖倒置原则的几个准则帮助你理解依赖倒置原则的几个准则 不要保存一个对具体类引用的变量 不要从一个具体类派生子类 不要覆盖超类任何方法的实现 这只是我们应当努力争取达到的准则,并不是任何时候都必须遵守的原则。但是,当我们要违背这些准则的时候,就应
28、当考虑是否有充足的理由要那样做。34回到回到PizzaStore 各地比萨经销店有相同的产品系列:Cheese Pizza、 Veggie Pizza 、 Clam Pizza 及Pepperoni Pizza 等。每一种产品也有相同的配料家族:dough、sauce、cheese、veggies、meats等。但是,同一产品在不同区域的配料的实现并不相同。35FrozenClamsPlumTomatoSauceThickCrustDoughMozzarellaCheeseFreshClamsMarinaraSauceThinCrustDoughReggianoCheeseCalamariBr
29、uschettaSauceVeryThinCrustGoatCheese薄壳面团Reggiano奶酪犁形番茄沙司白干酪奶酪乌贼很薄壳面团意大利烤面包沙司山羊奶酪配料家族配料家族冰冻蛤蜊新鲜蛤蜊厚壳面团番茄大蒜调味汁沙司36建造配料工厂建造配料工厂 为了保证各地比萨配料的质量,需要建造生产这些配料的工厂并将这些配料运往各地的经销店。 我们首先定义配料工厂的接口:public interface PizzaIngredientFactory public Dough createDough();public Sauce createSauce();public Cheese createChees
30、e();public Veggies createVeggies();public Pepperoni createPepperoni();public Clams createClam(); 37要做的事情要做的事情 为每一个地区建一个工厂。我们要创建PizzaIngredientFactory 的子类,实现每一个制造配料的方法。 实现各种配料类,例如,ReggianoCheese,RedPeppers, ThickCrustDough等。 将配料工厂插入PizzaStore代码。38建造建造New York配料工厂配料工厂public class NYPizzaIngredientFact
31、ory implements PizzaIngredientFactory public Dough createDough() return new ThinCrustDough(); public Sauce createSauce() return new MarinaraSauce(); / 番茄大蒜调味汁沙司 public Cheese createCheese() return new ReggianoCheese(); / Reggiano奶酪 39建造建造New York配料工厂配料工厂(续续)public Veggies createVeggies() Veggies veg
32、gies = new Garlic(), new Onion(), new Mushroom(), new RedPepper() ;return veggies; public Pepperoni createPepperoni() return new SlicedPepperoni();public Clams createClam() return new FreshClams();大蒜洋葱蘑菇辣椒 40修改修改Pizzapublic abstract class Pizza String name;Dough dough;Sauce sauce;Veggies veggies;Che
33、ese cheese;Pepperoni pepperoni;Clams clam;abstract void prepare();void bake() System.out.println(Bake for 25 minutes at 350);这个方法现在是抽象的。41修改修改Pizza(续续)void cut() System.out.println(Cutting the pizza into diagonal slices);void box() System.out.println(Place pizza in official PizzaStore box);void setN
34、ame(String name) = name;String getName() return name;public String toString() / 这里是打印比萨的代码42修改修改Pizza(续续)public class CheesePizza extends Pizza PizzaIngredientFactory ingredientFactory; public CheesePizza(PizzaIngredientFactory ingredientFactory) this.ingredientFactory = ingredientFactory;
35、 void prepare() System.out.println(Preparing + name);dough = ingredientFactory.createDough();sauce = ingredientFactory.createSauce();cheese = ingredientFactory.createCheese();43再访比萨店再访比萨店public class NYPizzaStore extends PizzaStore protected Pizza createPizza(String item) Pizza pizza = null;PizzaIng
36、redientFactory ingredientFactory = new NYPizzaIngredientFactory(); if (item.equals(cheese) pizza = new CheesePizza(ingredientFactory);pizza.setName(New York Style Cheese Pizza); 44再访比萨店再访比萨店(续续) else if (item.equals(veggie) pizza = new VeggiePizza(ingredientFactory);pizza.setName(New York Style Vegg
37、ie Pizza); else if (item.equals(clam) pizza = new ClamPizza(ingredientFactory);pizza.setName(New York Style Clam Pizza); else if (item.equals(pepperoni) pizza = new PepperoniPizza(ingredientFactory);pizza.setName(New York Style Pepperoni Pizza); return pizza; 45我们做了什么我们做了什么? 我们引入了一种新型工厂,称为抽象工厂抽象工厂,以
38、提供比萨配料家族的生产方法。 抽象工厂给出创建产品家族的接口产品家族的接口。通过给这个接口编码,去掉了制造产品的具体工厂的代码耦合。它允许我们实现许多工厂,生产各种不同背景的产品。46定义接口提供产品实现从抽象工厂,派生了一个或多个具体工厂,生产相同的产品,但是不同的实现。用具体工厂生产的配料,制作出的比萨。抽象原料工厂纽约芝加哥47订购比萨订购比萨(抽象工厂抽象工厂)我喜欢NY风格的。我要Chicago的。EthanJoel48订购比萨订购比萨(抽象工厂抽象工厂)(续续) 首先,我们需要一个NY PizzaStore:PizzaStore nyPizzaStore = new NYPizza
39、Store; 下订单:nyStore.orderPizza(“Cheese”); orderPizza()方法首先调用CreatePizza()方法:Pizza pizza = createPizza(“cheese”);上面的订购过程与以前是一样的。下面就有变化了,因为我们使用配料工厂。49订购比萨订购比萨(抽象工厂抽象工厂)(续续) 调用CreatePizza()方法的时候,就是配料工厂发挥作用 的时候:Pizza pizza = new CheesePizza(nyIngredientFactory); 下一步准备比萨。一旦调用了prepare()方法,就要求工 厂准备配料:void p
40、repare() System.out.println(Preparing + name);dough = ingredientFactory.createDough();sauce = ingredientFactory.createSauce();cheese = ingredientFactory.createCheese(); 最后,orderPizza()方法烘烤、切片及装盒准备出的比萨。50抽象工厂模式定义抽象工厂模式定义 我们已经看到:抽象工厂允许客户使用抽象的接口创建一系列的产品,而不需了解或关心具体生产的产品。在这种情况下,客户不再与具体产品的细节耦合在一起。抽象工厂模式提供
41、一个接口,创建相关或依赖的对象家族,而不指定具体的类。51AbstractFactoryCreateProductA()CreateProductB()ConcreteFactory1ConcreteFactory2CreateProductA()CreateProductB()CreateProductA()CreateProductB()ClientAbstractProductAProductA2ProductA1AbstractProductBProductB2ProductB1客户代码根据抽象工厂编写。运行时,与具体的工厂绑定在一起。抽象工厂定义了具体工厂必须实现的所有接口,这些接口
42、由一系列生产产品的方法组成。这是产品家族。每一个具体的工厂生产一个完整的产品系列。具体工厂实现了不同的产品家族。要创建一个产品,客户使用其中一个工厂,不必实例化一个产品对象。抽象工厂模式的类图抽象工厂模式的类图52createDough()createSauce()createCheese()createVeggies()createPepperoni()createClam() createDough() createSauce() createCheese() createVeggies() createPepperoni() createClam() createDough() crea
43、teSauce() createCheese() createVeggies() createPepperoni() createClam()PizzaIngredientFactoryNYPizzaIngredientFactoryChicagoPizzaIngredientFactoryNYPizzaStorecreatePizza()DoughThickCrustDoughThinCrustDoughSaucePlumTomotoSauceMarinaraSauceCheeseMozzarellaCheeseReggianoCheeseClamsFrozenClamsFreshClams抽象工厂的客户是两个PizzaStore实例:NYPizzaS
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- Prasugrel-hydroxy-thiolactone-生命科学试剂-MCE-3743
- 2-3-Dihydroxypropyl-pentadecanoate-生命科学试剂-MCE-1920
- 2025年度酒店客房客房设施设备维修承包经营与备件储备协议
- 2025年度二零二五年度玉米种植与农业观光旅游项目合作协议
- 二零二五年度汽车抵押贷款信用评级合同
- 二零二五年度张家界市别墅湖南商品房买卖合同
- 二零二五年度离婚协议书简易版(离婚后子女教育协议)
- 跨界合作小区内餐饮与其他行业的合作机会探索
- 个人房屋贷款抵押担保合同样本
- 九月股东出资合同书
- 保育员教学大纲和教学计划
- XX站SCADA系统升级改造施工方案(模板)
- 偶函数讲课课件
- 中医治疗“湿疹”医案72例
- 《X公司应收账款管理研究14000字(论文)》
- 交通工程公司乳化沥青储油罐拆除工程安全协议书
- YS/T 441.1-2014有色金属平衡管理规范第1部分:铜选矿冶炼
- GB/T 23791-2009企业质量信用等级划分通则
- 员工自主报告和举报事故隐患奖励汇总表
- 清代文学绪论
- 阿里云数字化转型生态介绍课件
评论
0/150
提交评论