java工厂设计模式.ppt_第1页
java工厂设计模式.ppt_第2页
java工厂设计模式.ppt_第3页
java工厂设计模式.ppt_第4页
java工厂设计模式.ppt_第5页
已阅读5页,还剩45页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

The Factory Pattern (工厂模式) 学习问题 n随着经济的全球化,一个软件可能要在 全球销售。因此,我们设计的软件应该 能够通过简单的配置就可以适应不同的 国家。 n本讲所学的知识将能提供一种有助于解 决此问题的方法。 对象创建问题 n关于new: n按照面向抽象的设计原则,我们应该面向 接口编程而不是面向实现编程。但是我们 每次使用new时,是不是正在违背这一原 则呢? 我们想用接口但却必须建立一个 具体类的实例 Duck duck = new MallardDuck() 问题 n当你拥有一组相关的具体类时,你常常被迫写 出类似下面的代码: Duck duck; If (picnic) duck=new MallardDuck(); else if (hunting) duck=new DecoyDuck(); else if (inBathTub) duck=new RubberDuck(); 这样做的原因是 直到运行时我们 才知道需要实例 化那个类。 这样做的后果是 如果应用要做变 化或扩展,往往 要修改这段代码 。这使得维护困 难并容易引入错 误。 问题在哪里?是new的问题吗? n从技术上来说,new并没有任何问题。 new是java最基本的部分。真正的问题在 于“变化” n如果对接口编程,我们可实现与许多“变 化”的隔离,因为通过多态机制,你的代 码对于实现接口的新类依然适用。但是 使用具体类麻烦就来了,因为增加新的 具体类时相应代码可能就必须修改。 怎么办呢? nDuck duck = new MallardDuck() n上面这段代码所在的模块与MallardDuck 模块形成了耦合。 再回忆我们前面提出的面向对象 设计的原则 识别应用的变化部分,并将之与固 定的部分相分离。 区分变化的部分 下面我们来看一个例子 Pizza店 披萨 PizzaStore类中的一段代码-订做pizza Public Class PizzaStore / Pizza orderPizza() Pizza pizza = new Pizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; / 真希望这是 一个抽象类 或者接口, 可惜抽象类 或接口都不 能被实例化 而且,我们有许多 种pizza,所以我们 增加一些代码,来 确定合适的pizza种 类,然后进行制作 。 修改后的代码 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”) pizza = new PepperoniPizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; 根据接受的类型,创 建相应的pizza实例, 并赋值给实例变量。 (注意:各种pizza实 现接口Pizza) 传递pizza的 类型给方法 orderPizza 每一种pizza子类型都 知道其制作方法 由于市场竞争。 n其他pizza店推出了新产品,我们也得增 加!例如VeggiePizza。 nGreekPizza最近不受欢迎,把它从菜单中 取消。 n于是。 改!改!改! 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”) pizza = new PepperoniPizza(); else if (type.equals(“veggie”) pizza = new VeggiePizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; 变与不变 变与不变 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”) pizza = new PepperoniPizza(); else if (type.equals(“veggie”) pizza = new VeggiePizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; 这是变化的部分。随 着Pizza菜单的变化, 这部分要跟着不断地 变。 这部分是不变的 部分。 分离 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”) pizza = new PepperoniPizza(); else if (type.equals(“veggie”) pizza = new VeggiePizza(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; 把这部分封装在一个 只管如何创建pizza的 对象中 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(“veggie”) pizza = new VeggiePizza(); 将创建pizza对象的 代码从orderPizza方法 中分离出去 专管制作 pizza的对象 我们将专管制作pizza的对象叫做Pizza工厂 Pizza orderPizza(String type) Pizza pizza; pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; PizzaFactory 要求制作pizza pizza 这样,orderPizza方法 就成为PizaFactory的客 户。 Pizza工厂-SimplePizzaFactory public class SimplePizzaFactory public Pizza createPizza(String type) Pizza pizza=null; if (type.equals(“cheese”) pizza = new CheesePizza(); else if (type.equals(“pepperoni”) pizza = new PepperoniPizza(); else if (type.equals(“veggie”) pizza = new VeggiePizza(); return pizza; Pizza工厂中定义了 “生 产”pizza的方法。所有 客户都可以用它来实例 化新的pizza对象 这部分代码就是 从orderPizza()方 法中抽出来的。 和原来的方法一 样,也是通过参 数确定pizza的种 类。 思考一下! n这看来好像我们只是把问题从一个对象推给了 另一个对象!这样做有什么好处呢? n可以解除客户代码(PizzaStore)与具体Pizza的 耦合。 nSimplePizzaFactory可以有许多个客户,这样, 当实现改变时我们只需要修改 SimplePizzaFactory,而不需修改众多的客户。 n提高了聚合度,PizzaStore的职责是使用pizza对 象, SimplePizzaFactory的职责是决定创建什么 样的pizza对象。 重写PizzaStore类 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; /other methods here 简单工厂模式 PizzaStore orderPizza() SimplePizzaFactory createPizza() Pizza Prepare() Bake() Cut() Box() CheesePizza VeggiePizzaClamPizza PepperoniPizza Pizza可以是 一个抽象类, 也可以是一个 接口。 PizzaStore1 orderPizza() 框架 框架的 对外接口 简单工厂模式 Client orderProduct() SimpleFactory createProduct() AbstractProduct methodOfProduct() Product1 Product2Product3 Productn有人认为这还不 是一个真正的模 式,只是一种程 序设计的习惯。 授权pizza店 n我们的pizza店非常成功,许多人都想开 设我们的授权加盟店。 n但是,不同地区的加盟pizza店可能希望 供应不同口味的pizza。怎么解决这个问 题呢? 解决方法之一:建立不同的工厂 n建立不同的工厂:如NYPizzaFactory、 ChicagoPizzaFactory、 CaliforniaPizzaFactory,在PizzaStore中包含相应工厂的实例。其代 码类似于: /该pizza店提供纽约风味的pizza NYPizzaFactory nyFactory=new NYPizzaFactory();/建立一个生产纽 约风味pizza的工厂 PizzaStore nyStore=new PizzaStore(nyFactory);/建立一个pizza店 ,引用纽约风味pizza的工厂 nyStore.orderPizza(“Veggie”);/生产的是纽约风味的pizza /该pizza店提供芝加哥风味的pizza ChicagoPizzaFactory chicagoFactory=new ChicagoPizzaFactory(); PizzaStore chicagoStore=new PizzaStore(chicagoFactory); chicagoStore.orderPizza(“Veggie”); 抽象工厂模式 n这么多工厂,可以再增加抽象层 n让我们一起来设计 AbstractFactory createProduct() ConcreteFactory createProduct() 另一种解决方法-工厂方法模式 n思路:改写的PizzaStore,将 createPizza()方法放回到PizzaStore,但 是声明为抽象方法,然后,为每一种地 方风味创建一个PizzaStore的子类。 改造后的PizzaStore的代码 public abstract class 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); 在PizzaStore内调用自 身的一个方法来制造 pizza,而不是使用一个 factory对象 factory对象成了这里的 一个抽象方法 下面我们需要PizzaStore的各种子类(对应不同 的地区风味) 让子类做决定 PizzaStore createPizza() orderPizza() NYPizzaStore createPizza() ChicagoPizzaStore createPizza() Pizza createPizza(String item) if (item.equals(“奶酪“) return new NYStyleCheesePizza(); else if (item.equals(“蔬菜“) return new NYStyleVeggiePizza(); else if (item.equals(“卡姆“) return new NYStyleClamPizza(); else if (item.equals(“辣香肠“) return new NYStylePepperoniPizza(); else return null; 讨论:为什么说是由子类做决定的? PizzaStore createPizza() orderPizza() NYPizzaStore createPizza() ChicagoPizzaStore createPizza() public abstract class 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); 现在让我们来编写子类NYPizzaStore PizzaStore createPizza() orderPizza() NYPizzaStore createPizza() ChicagoPizzaStore createPizza() public class NYPizzaStore extends PizzaStore Pizza createPizza(String item) if (item.equals(“奶酪“) return new NYStyleCheesePizza(); else if (item.equals(“蔬菜“) return new NYStyleVeggiePizza(); else if (item.equals(“卡姆“) return new NYStyleClamPizza(); else if (item.equals(“辣香肠“) return new NYStylePepperoniPizza(); else return null; 怎么编写子类ChicagoPizzaStore? 试试看 声明工厂方法 public abstract class 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); 实例化pizza的责 任现在由一个方 法承担。该方法 相当于一个工厂 。我们称之为工 厂方法。 PizzaStore的子类 用createPizza() 方法处理对象的 实例化。 声明工厂方法 abstract Pizza createPizza(String type); abstract Product factoryMethod(String type); n工厂方法是抽象的,在一个超类中定义。必须 由子类来实现。 n工厂方法返回一个产品,该产品通常在其所在 类的方法中定义。(如orderPizza()) n工厂方法通常提供参数,用以选择一个产品的 不同品种。 n工厂方法将客户(超类中的方法,如 PizzaStore中的orderPizza())与具体的产品相 隔离。 工厂方法怎么工作? n假定张三喜欢纽约风味的pizza,李四 喜欢芝加哥风味的pizza。 1.需要相应Pizza店的实例 2.调用orderPizza()订购想要的pizza品种 3.createPizza()被调用,并返回pizza到 orderPizza()方法。 4.尽管不知道是什么pizza,但 orderPizza()仍知道对它进行后续处理 。 以张三订购pizza为例 nPizzaStore nyPizzaStore=new NYPizzaStore(); nnyPizzaStore.orderPizza(“cheese”) n在orderPizza()方法中 Pizza pizza=createPizza (“cheese”) ; n在orderPizza()方法中 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); 忘记了产品:pizza,先来个抽象的 import java.util.ArrayList; public abstract class Pizza String name; String dough; /生面团 String sauce; ArrayList toppings = new ArrayList(); void prepare() System.out.println(“Preparing “ + name); System.out.println(“Tossing 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); void bake() System.out.println(“Bake for 25 minutes at 350“); void cut() System.out.println(“Cutting the pizza into diagonal slices“); void box() System.out.println(“Place pizza in official PizzaStore box“); public String getName() return name; 再来个具体的 public class NYStyleCheesePizza extends Pizza public NYStyleCheesePizza() name = “NY Style Sauce and Cheese Pizza“; dough = “Thin Crust Dough“; sauce = “Marinara Sauce“; toppings.add(“Grated Reggiano Cheese“); Marinara (mariners) sauce is an Italian red sauce usually made with tomatoes, garlic, herbs (such as basil), and onion 再来个另一风味的 public class ChicagoStyleCheesePizza extends Pizza public ChicagoStyleCheesePizza() name = “Chicago Style Deep Dish Cheese Pizza“; dough = “Extra Thick Crust Dough“; sauce = “Plum Tomato Sauce“; toppings.add(“Shredded Mozzarella Cheese“); void cut() System.out.println(“Cutting the pizza into square slices“); 测试主类 public class PizzaTestDrive public static void main(String args) PizzaStore nyStore = new NYPizzaStore(); PizzaStore chicagoStore = new ChicagoPizzaStore(); Pizza pizza = nyStore.orderPizza(“cheese“); System.out.println(“张三 ordered a “ + pizza.getName() + “n“); pizza = chicagoStore.orderPizza(“cheese“); System.out.println(“李四 ordered a “ + pizza.getName() + “n“); 工厂方法模式中的类 创建者类 The Creator classes PizzaStore createPizza() orderPizza() NYPizzaStore createPizza() ChicagoPizzaStore createPizza() Abstract creator Concrete creators 工厂方法模式中的类 产品类 The Product classes Pizza NYStyleCheesePizzaChicagoStyleCheesePizza createPizza() NYStylePepperoniPizza NYStyleCalmPizza NYStyleVeggiePizza ChicagoStylePepperoniPizza createPizza() ChicagoStyleCalmPizza createPizza() ChicagoStyleVeggiePizza createPizza() Abstract product Concrete products 工厂方法模式的正式定义 n在类中定义一个用于创建对象的接口方法,让 其子类决定实例化哪一个类。通过这种做法, 使得工厂方法的客户(工厂方法的使用者)不 必了解具体应该实例化哪一个类。 n如: pizza = pizzaStore.orderPizza(“cheese“); 生产出来的匹萨是纽约风味的还是芝加哥风味的取决于pizzaStore引 用的是哪个PizzaStore的子类 工厂方法模式的结构 Product ConcreteCreator factoryMethod() ConcreteProduct Creator factoryMethod() anOperation 总结:Factory Method模式 n意图 n定义一个用于创建对象的接口,让子类决定 实例化哪一个类。工厂方法模式让一个类的 实例化延迟到其子类。使得对象的创建与对 象的使用分离开来。 n别名 n虚拟构造器 工厂方法模式的优点与适用场景 n优点 n让用户代码与特定类Product的子类ConcretProduct 的代码解耦。 n用户不必知道它所使用的对象是怎么创建的,只需 要知道这些对象的用法即可。 n适用场景 n希望让用户使用某些类,但不希望与这些类形成耦 合(用new)。 n用户需要一个类的子类的实例,但不知道该类有哪 些子类可用。 工厂方法模式的好处 Product ConcreteCreator factoryMethod() ConcreteProduc

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论