意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。
结构:
实例:下面我们以Pizza店的例子来谈谈“工厂方法模式”的来龙去脉,我们学习的思路是“原始设计-->简单工厂-->工厂方法”。
情景分析:假如你有一个Pizza店,那么你的Pizza订单可能会写成如下代码(这段代码写在PizzaStore类里面):
2 {
3 Pizza pizza = new Pizza();
4 pizza.Prepare();
5 pizza.Bake();
6 pizza.Cut();
7 pizza.Box();
8 return pizza;
9 }
10
如果你的Pizza店的Pizza有很多类,那么你的Pizza订单会如何写呢,可能会写成如下:
2 {
3 public Pizza OrderPizza(String paramPizzaType)
4 {
5 Pizza pizza = null;
6 if (paramPizzaType.Equals("cheese"))
7 {
8 pizza = new CheesePizza();
9 }
10 else if (paramPizzaType.Equals("greek"))
11 {
12 pizza = new GreekPizza();
13 }
14 else if (paramPizzaType.Equals("pepperon"))
15 {
16 pizza = new PepperoniPizza();
17 }
18 pizza.Prepare();
19 pizza.Bake();
20 pizza.Cut();
21 pizza.Box();
22 return pizza;
23 }
24
25 // 省略
26 }
27
上面的代码有一个问题:当Pizza的种类发生改变(或增加或减少)时,这段代码必须重写。那么这段代码应该如何改进呢?其实我们只要封装变化点就行了,即代码中的“if,else”语句。封装的过程如下:
1)、创建SimplePizzaFactory类。
2)、在SimplePizzaFactory类中创建CreatPizza方法。
3)、把“if,else”语句写道CreatPizza方法中。
相应的代码如下:
2 {
3 public Pizza CreatPizza(String paramPizzaType)
4 {
5 Pizza pizza = null;
6 if (paramPizzaType.Equals("cheese"))
7 {
8 pizza = new CheesePizza();
9 }
10 else if (paramPizzaType.Equals("greek"))
11 {
12 pizza = new GreekPizza();
13 }
14 else if (paramPizzaType.Equals("pepperon"))
15 {
16 pizza = new PepperoniPizza();
17 }
18 return pizza;
19 }
20 }
21
这样做的好处:
1)、可以很好的达到代码重用。如果其他类想得到Pizza,都可以调用SimplePizzaFactory的CreatPizza()方法。
2)、维护方便。如果Pizza的创建需要改变,只需要改变CreatPizza()方法就行了,其他调用的地方不需要发生改变。
值得改进的地方:可以把CreatPizza()写成静态方法。
改成静态方法的优点:不需要通过创建对象来使用类里的方法。
缺点:不能通过继承来改变创建对象的行为。
小结:
上面的代码其实是简单工厂模式的应用(简单工厂不是一个真正的模式)。
简单工厂(Simple Factory)模式的意图:Simple Factory模式根据提供给它的数据,返回几个可能类中的一个类的实例。通常它返回的类都有一个公共的父类和公共的方法。
结构:
工厂类角色Creator (SimplePizzaFactory):工厂类在客户端的直接控制下(Create方法)创建产品对象。
抽象产品角色Product (Pizza):定义简单工厂创建的对象的父类或它们共同拥有的接口。可以是一个类、抽象类或接口。
具体产品角色ConcreteProduct (CheesePizza, GreekPizza,PepperoniPizza):定义工厂具体加工出的对象。
客户端Client(PizzaStore):负责调用SimplePizzaFactory的Create方法。
其实SimplePizzaFactory的CreatPizza()方法并没有符合面向对象的开闭原则,它没有对修改进行关闭,即当Pizza的种类改变时,这个方法必须重写,只不过改动的工作量减少了,只需要改动一处,其他调用的地方不需要变动而已。
新的需求:
1)、Pizza店有了加盟店,加盟店生产Pizza的流程应该一成不变。
2)、每个加盟店可能要提供不同风味的Pizza(比如纽约、芝加哥、加州)。
按照简单工厂的方法,我们可以这样做:创建NYPizzaFactory、ChicagoPizzaFactory、CaliforniaPizzaFactory类。相应的代码如下:
2 PizzaStore nyStore = new PizzaStore(nyFactory); // 建立Pizza店,经营纽约风味的Pizza
3 nyStore.OrderPizza("cheese"); // 订购具有纽约风味的CheesePizza
如果需求不发生改变,那么用简单工厂就已经足够了,但是一旦需求发生了变化,简单工厂就不能适应了。
变化后的需求:
1)、有些加盟店采用自创的流程,比如烘烤的做法有些差异(Bake方法改变)、不要切片(Cut方法不要)、采用其他公司的盒子(Box方法改变)等。
2)、Pizza的种类有可能发生改变(或增加或减少)。
我们的做法很简单,具体操作:
1)、把SimpleFactory的CreatPizza()方法写回到PizzaStore里面。
2)、抽象PizzaStore,用NYPizzaStore、ChicagoPizzaStore等继承PizzaStore。
3)、具体的PizzaStore和具体的Pizza进行一一对应。
相应的类图如下(应用了工厂方法模式):
说明:
1)、PizzaStore类是抽象类,相当于工厂方法模式的Creator类,NYPizzaStore类和ChicagoPizzaStore类继承了PizzaStore,相当于工厂方法模式的ConcreteCreator。
2)、Pizza是抽象类,相当于Product类,NYStyleCheesePizza类、NYStylePepperoniPizza类、 NYStyleGreekPizza类、ChicagoStyleCheesePizza类、ChicagoStylePepperoniPizza类、 ChicagoStyleGreekPizza类继承了Pizza类,相当于ConcreteProduct。
3)、NYPizzaStore类调用了NYStyleCheesePizza类、NYStylePepperoniPizza类、 NYStyleGreekPizza类,ChicagoPizzaStore类调用了ChicagoStyleCheesePizza类、 ChicagoStylePepperoniPizza类、ChicagoStyleGreekPizza类。
相应的代码如下:
工厂方法模式的特点:
1)、核心的工厂类不负责所有产品的创建,而是将具体创建工作交给子类去做,可以允许系统在不修改工厂角色的情况下引进新产品。
2)、工厂类与产品类往往具有平行的等级结构,它们之间一一对应。
工厂方法和简单工厂的区别:
1)、Factory Method 的核心是一个抽象工厂类,而Simple Factory 把核心放在一个具体类上。
2)、Factory Method 的具体工厂类都有共同的接口,或者有共同的抽象父类。
3)、当系统扩展需要添加新的产品对象时,Factory Method仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了“开放-封闭”原则。而 Simple Factory 在添加新产品对象后不得不修改工厂方法,扩展性不好。
发表评论
-
《Head.First设计模式》的学习笔记(17)-综合例子
2012-02-12 00:53 0例子: -
《Head.First设计模式》的学习笔记(16)--复合模式
2012-02-12 00:51 0意图: -
《Head.First设计模式》的学习笔记(15)--代理模式
2012-02-13 00:03 1127意图: 为另一个对象提供一个替身或占位符得以访问这个对象。 ... -
《Head.First设计模式》的学习笔记(14)--状态模式
2012-02-12 20:24 1224意图:允许对象在内部状态改变时改变她的行为,对象看起来好像修改 ... -
《Head.First设计模式》的学习笔记(13)--组合模式
2012-02-12 17:49 811先说一下题外话,这个模式是我学的最累的模式,代码纠结无比,而且 ... -
《Head.First设计模式》的学习笔记(12)--迭代器模式
2012-02-12 15:30 714意图:提供一种方法顺序访问一个聚合对象中的各个元素,而又不 ... -
《Head.First设计模式》的学习笔记(11)--模板方法模式
2012-02-12 00:46 846意图:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中 ... -
《Head.First设计模式》的学习笔记---前言
2012-02-11 23:36 0headfist系列博客从这篇--模版方法模式开始自己写的了, ... -
《Head.First设计模式》的学习笔记(10)--外观模式
2012-02-11 23:30 640意图:为子系统中的一组接口提供一个一致的界面,Facade ... -
《Head.First设计模式》的学习笔记(9)--适配器模式
2012-02-11 23:27 704软件开发中经常遇到的 ... -
《Head.First设计模式》的学习笔记(8)--命令模式
2012-02-11 22:55 689背景:有时候我们需要对方法进行封装,通过对这些封装的方法进行调 ... -
《Head.First设计模式》的学习笔记(7)--单件模式
2012-02-11 13:55 881背景:有一些对象其实我们只需要一个,比方说:线程池(threa ... -
《Head.First设计模式》的学习笔记(6)--抽象工厂模式
2012-02-11 13:37 819意图:提供一个接口,用于创建相关或依赖对象的家族,而不需要明 ... -
《Head.First设计模式》的学习笔记(4)--装饰者模式
2012-02-10 23:40 781意图:动态地将责任 ... -
《Head.First设计模式》的学习笔记(3)--观察者模式
2012-02-10 23:27 697意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改 ... -
《Head.First设计模式》的学习笔记(2)--策略模式
2012-02-10 23:09 604先对策略模式有一个总体认识。 意图:定义一系列的算法,把它们 ... -
《Head.First设计模式》的学习笔记(1)
2012-01-31 21:53 7561、慢一点,你理解的越 ...
相关推荐
Head.First 设计模式学习笔记.pdf Head.First 设计模式学习笔记.pdf
HeadFirst 设计模式学习笔记3--装饰模式 Demo http://blog.csdn.net/laszloyu/archive/2010/05/12/5582561.aspx
HeadFirst 设计模式学习笔记2--观察者模式 demo http://blog.csdn.net/laszloyu/archive/2010/05/12/5581769.aspx
http://blog.csdn.net/laszloyu/archive/2010/05/11/5579765.aspx 示例代码
HeadFirst设计模式学习笔记比较全面详细地讲解了13个设计模式,有利于大家更好的学习HeadFirst设计模式,希望亲们会喜欢~~~
Head First 设计模式学习笔记。更多内容请参见文章内容。
著名的《Head First Design Pattern》学习笔记,摘要这本书中的设计思路。由于书本过长,整理出笔记帮助回想起设计模式。文件是docx格式,只能由OFFICE Word 2007之后的版本打开,内附Visio类图文件。本文由个人整理...
NULL 博文链接:https://chxiaowu.iteye.com/blog/1276845
设计模式Head First学习笔记,以及使用java编写的设计模式源码,Java原生sdk实现23种设计模式
学习设计模式时,做的笔记,主要参考了《Head First设计模式》
VS2005 ASP.NET本地化学习笔记&感受 在自定义Server Control中捆绑JS文件 Step by Step 深度解析Asp.Net2.0中的Callback机制 使用 Web 标准生成 ASP.NET 2.0 Web 站点 ASP.NET 2.0基于SQLSERVER 2005的aspnetdb.mdf...
最近在设计模式的一些内容,主要的参考书籍是《Head First 设计模式》,同时在学习过程中也查看了很多博客园中关于设计模式的一些文章的,在这里记录下我的一些学习笔记,一是为了帮助我更深入地理解设计模式,二...
近在学设计模式的一些内容,主要的参考书籍是《Head First 设计模式》,同时在学习过程中也查看了很多博客园中关于设计模式的一些文章的,在这里记录下我的一些学习笔记,一是为了帮助我更深入地理解设计模式,二...
Head First学习笔记+Head First之装饰者模式高清PDF
设计模式、设计模式 可复用面向对象软件的基础,实现了 Gof 的 23 种设计模式。 内容包括三大原则(继承、封装、多态)、类图、设计原则。 数据库 :floppy_disk: 参考 数据库系统原理。 参考 SQL 必知必会。 ...
学习笔记都在这里了 好好学习,天天向上!生命不息,阅读不止! 本仓库参考以下书籍或资料 JavaScript高级程序设计(第三版) You don't know JS 系列 ES6 标准入门 Node.JS深入浅出 图解HTTP HTTP权威指南 Head First...