java工厂设计模式.ppt

上传人:小飞机 文档编号:6509774 上传时间:2023-11-07 格式:PPT 页数:50 大小:962.50KB
返回 下载 相关 举报
java工厂设计模式.ppt_第1页
第1页 / 共50页
java工厂设计模式.ppt_第2页
第2页 / 共50页
java工厂设计模式.ppt_第3页
第3页 / 共50页
java工厂设计模式.ppt_第4页
第4页 / 共50页
java工厂设计模式.ppt_第5页
第5页 / 共50页
点击查看更多>>
资源描述

《java工厂设计模式.ppt》由会员分享,可在线阅读,更多相关《java工厂设计模式.ppt(50页珍藏版)》请在三一办公上搜索。

1、The Factory Pattern(工厂模式),学习问题,随着经济的全球化,一个软件可能要在全球销售。因此,我们设计的软件应该能够通过简单的配置就可以适应不同的国家。本讲所学的知识将能提供一种有助于解决此问题的方法。,对象创建问题,关于new:按照面向抽象的设计原则,我们应该面向接口编程而不是面向实现编程。但是我们每次使用new时,是不是正在违背这一原则呢?,我们想用接口,但却必须建立一个具体类的实例,Duck duck=new MallardDuck(),问题,当你拥有一组相关的具体类时,你常常被迫写出类似下面的代码:Duck duck;If(picnic)duck=new Mallar

2、dDuck();else if(hunting)duck=new DecoyDuck();else if(inBathTub)duck=new RubberDuck();,这样做的原因是直到运行时我们才知道需要实例化那个类。,这样做的后果是如果应用要做变化或扩展,往往要修改这段代码。这使得维护困难并容易引入错误。,问题在哪里?是new的问题吗?,从技术上来说,new并没有任何问题。new是java最基本的部分。真正的问题在于“变化”如果对接口编程,我们可实现与许多“变化”的隔离,因为通过多态机制,你的代码对于实现接口的新类依然适用。但是使用具体类麻烦就来了,因为增加新的具体类时相应代码可能就必

3、须修改。,怎么办呢?,Duck duck=new MallardDuck()上面这段代码所在的模块与MallardDuck模块形成了耦合。,再回忆我们前面提出的面向对象设计的原则,识别应用的变化部分,并将之与固定的部分相分离。,区分变化的部分,下面我们来看一个例子Pizza店,披萨,PizzaStore类中的一段代码-订做pizza,Public Class PizzaStore/Pizza orderPizza()Pizza pizza=new Pizza();pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;

4、/,真希望这是一个抽象类或者接口,可惜抽象类或接口都不能被实例化,而且,我们有许多种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

5、();pizza.bake();pizza.cut();pizza.box();return pizza;,根据接受的类型,创建相应的pizza实例,并赋值给实例变量。(注意:各种pizza实现接口Pizza),传递pizza的类型给方法orderPizza,每一种pizza子类型都知道其制作方法,由于市场竞争。,其他pizza店推出了新产品,我们也得增加!例如VeggiePizza。GreekPizza最近不受欢迎,把它从菜单中取消。于是。,改!改!改!,Pizza orderPizza(String type)Pizza pizza;if(type.equals(“cheese”)pizz

6、a=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

7、;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菜单的变化,

8、这部分要跟着不断地变。,这部分是不变的部分。,分离,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.

9、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对象的代码从orde

10、rPizza方法中分离出去,专管制作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 creat

11、ePizza(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()方法中抽出来的。和原来的方法一样,也是通过参数

12、确定pizza的种类。,思考一下!,这看来好像我们只是把问题从一个对象推给了另一个对象!这样做有什么好处呢?可以解除客户代码(PizzaStore)与具体Pizza的耦合。SimplePizzaFactory可以有许多个客户,这样,当实现改变时我们只需要修改SimplePizzaFactory,而不需修改众多的客户。提高了聚合度,PizzaStore的职责是使用pizza对象,SimplePizzaFactory的职责是决定创建什么样的pizza对象。,重写PizzaStore类,public class PizzaStore SimplePizzaFactory factory;public

13、 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,简单工厂模式,Pizza可以是一个抽象类,也可以是一个接口。,框架,框架的对外接口,简单工厂模式,有人认为这还不是一个真正的模式,只是一种程序设计的

14、习惯。,授权pizza店,我们的pizza店非常成功,许多人都想开设我们的授权加盟店。但是,不同地区的加盟pizza店可能希望供应不同口味的pizza。怎么解决这个问题呢?,解决方法之一:建立不同的工厂,建立不同的工厂:如NYPizzaFactory、ChicagoPizzaFactory、CaliforniaPizzaFactory,在PizzaStore中包含相应工厂的实例。其代码类似于:/该pizza店提供纽约风味的pizzaNYPizzaFactory nyFactory=new NYPizzaFactory();/建立一个生产纽约风味pizza的工厂PizzaStore nyStor

15、e=new PizzaStore(nyFactory);/建立一个pizza店,引用纽约风味pizza的工厂nyStore.orderPizza(“Veggie”);/生产的是纽约风味的pizza/该pizza店提供芝加哥风味的pizzaChicagoPizzaFactory chicagoFactory=new ChicagoPizzaFactory();PizzaStore chicagoStore=new PizzaStore(chicagoFactory);chicagoStore.orderPizza(“Veggie”);,抽象工厂模式,这么多工厂,可以再增加抽象层让我们一起来设计,

16、另一种解决方法-工厂方法模式,思路:改写的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

17、createPizza(String type);,在PizzaStore内调用自身的一个方法来制造pizza,而不是使用一个factory对象,factory对象成了这里的一个抽象方法,下面我们需要PizzaStore的各种子类(对应不同的地区风味),让子类做决定,ChicagoPizzaStore,createPizza(),Pizza createPizza(String item)if(item.equals(“奶酪)return new NYStyleCheesePizza();else if(item.equals(“蔬菜)return new NYStyleVeggiePizza

18、();else if(item.equals(“卡姆)return new NYStyleClamPizza();else if(item.equals(“辣香肠)return new NYStylePepperoniPizza();else return null;,讨论:为什么说是由子类做决定的?,ChicagoPizzaStore,createPizza(),public abstract class PizzaStore public Pizza orderPizza(String type)Pizza pizza=createPizza(type);pizza.prepare();p

19、izza.bake();pizza.cut();pizza.box();return pizza;abstract Pizza createPizza(String type);,现在让我们来编写子类NYPizzaStore,ChicagoPizzaStore,createPizza(),public class NYPizzaStore extends PizzaStore Pizza createPizza(String item)if(item.equals(“奶酪)return new NYStyleCheesePizza();else if(item.equals(“蔬菜)retur

20、n 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.

21、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);工厂方法是抽象的,在一个超类中定义。必须由子类来实现

22、。工厂方法返回一个产品,该产品通常在其所在类的方法中定义。(如orderPizza())工厂方法通常提供参数,用以选择一个产品的不同品种。工厂方法将客户(超类中的方法,如PizzaStore中的orderPizza())与具体的产品相隔离。,工厂方法怎么工作?,假定张三喜欢纽约风味的pizza,李四喜欢芝加哥风味的pizza。需要相应Pizza店的实例调用orderPizza()订购想要的pizza品种createPizza()被调用,并返回pizza到orderPizza()方法。尽管不知道是什么pizza,但orderPizza()仍知道对它进行后续处理。,以张三订购pizza为例,Piz

23、zaStore nyPizzaStore=new NYPizzaStore();nyPizzaStore.orderPizza(“cheese”)在orderPizza()方法中 Pizza pizza=createPizza(“cheese”);在orderPizza()方法中 pizza.prepare();pizza.bake();pizza.cut();pizza.box();,忘记了产品:pizza,先来个抽象的,import java.util.ArrayList;public abstract class Pizza String name;String dough;/生面团St

24、ring 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(

25、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 Sauc

26、e 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 ChicagoStyleCheeseP

27、izza()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=n

28、ew 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,ChicagoPizzaStore,

29、createPizza(),Abstract creator,Concrete creators,工厂方法模式中的类产品类 The Product classes,Abstract product,Concrete products,工厂方法模式的正式定义,在类中定义一个用于创建对象的接口方法,让其子类决定实例化哪一个类。通过这种做法,使得工厂方法的客户(工厂方法的使用者)不必了解具体应该实例化哪一个类。如:pizza=pizzaStore.orderPizza(cheese);生产出来的匹萨是纽约风味的还是芝加哥风味的取决于pizzaStore引用的是哪个PizzaStore的子类,工厂方法

30、模式的结构,总结:Factory Method模式,意图定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法模式让一个类的实例化延迟到其子类。使得对象的创建与对象的使用分离开来。别名虚拟构造器,工厂方法模式的优点与适用场景,优点让用户代码与特定类Product的子类ConcretProduct的代码解耦。用户不必知道它所使用的对象是怎么创建的,只需要知道这些对象的用法即可。适用场景希望让用户使用某些类,但不希望与这些类形成耦合(用new)。用户需要一个类的子类的实例,但不知道该类有哪些子类可用。,工厂方法模式的好处,用户程序只需要和这些类打交道,总结:Factory Method参与

31、者,Product(document)定义工厂方法所创建对象的接口。ConcreteProduct(mydocument)实现product接口。Creator(application)声明工厂方法可以调用工厂方法以创建一个product对象ConcreteCreator(MyApplication)重新定义工厂方法,以返回一个ConcreteProduct实例,工厂方法的经典范例:java迭代器,Collection接口中定义了iterator()方法,所有的集合类都实现了这个方法。iterator()方法就是一个工厂方法。其使用者不必了解需要实例化哪个类。import java.util.

32、*;public class ShowIterator public static void main(String args)List list=Arrays.asList(new String“fountaun”,”rocket”,“tree”);Iterator iter=list.iterator();while(iter.hasNext()System.out.println(iter.next();,抽象工厂解决的问题,抽象工厂模式是避免必须修改所有new调用问题的一个有效策略。抽象工厂的所有具体化有一个共同的主题,使用工厂来创建实现了已知接口,但类型尚不明确的对象。抽象工厂一般与

33、单例模式联系在一起。由单例模式获得抽象工厂,由抽象工厂制造实际类型未知的产品对象。经典例句Image im=Toolkit.getDefaultToolkit().createImage(i);每次调用getDefaultToolkit()方法得到的是同一个Toolkit实例。createImage()是Toolkit的一个方法。,习题(上机完成),某连锁超市为留住顾客,决定发行会员卡。会员卡分为金卡、银卡、普通卡等多种类型,卡的类型可能还会增加。不论是什么卡,其编号都是统一编制的,即使用同一个编号序列。某软件公司承接了该项目,设计人员觉得应该将系统设计的具有一定的通用性,不仅可以较方便的应对该连锁店的需求变化(增减卡的类型),而且可以较容易的修改扩展,为其他公司提供发卡(卡的风格可能不同)服务。假定你是该软件公司的设计师,请你运用学过的设计模式设计该系统的架构。编写实验报告,要求画出相应的类图,提供示意性java源程序。实验报告发至.,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号