第十二章 简单工厂模式
首先给出简单工厂模式的一个示意图:
简单工厂模式就是由一个工厂类根据传入的参量决定创建出哪一种产品类的实例。
对于多层次的产品结构如下:
图中从Factory类到各个Product类的虚线代表创建(依赖)关系;从Client到其他类的连线是一般依赖关系。
这样做的好处是设计简单,产品类的等级结构不会反映到工厂类中来,从而产品类的等级结构的变化也就不会影响到工厂类。但是这样做的缺点是,增加新的产品必将导致工厂类的修改。
使用java接口或者java抽象类
如果模式所产生的具体产品类彼此之间没有共同的商业逻辑,那么抽象产品角色可以由一个java接口扮演,相反,如果这些具体产品类彼此之间确实有共同的商业逻辑,那么这些共有的逻辑就应该移到抽象角色里面,这就意味着抽象角色应当由一个抽象类扮演。在一个类型的等级结构里面,共同的代码应当尽量向上移动,已达到共享的目的。
简单工厂模式的缺点
当产品类有不同的接口种类时,工厂类需要判断在什么时候创建某种产品。这种对时机的判断和对哪一种具体产品的判断逻辑混合在一起,使得系统在将来进行功能扩展时较为困难。这一缺点在工厂方法模式中得到克服
开闭原则
在这个系统中,功能的扩展体现在引进新的产品上。开闭原则要求系统允许当新的产品加入系统中时,而无需对现有代码进行修改。这一点对于产品的消费角色是成立的,而对于工厂角色是不成立的。。(在增加一个产品类的时候,需要修改工厂类,这不符合开闭原则)
简单工厂代码:
产品:水果,葡萄,草莓,苹果。
水果接口:
public interface Fruit { void harvest(); void plant(); }
苹果:
public class Apple implements Fruit { private int treeAge; public void grow() { log("Apple is growing.."); } public void harvest() { log("Apple has been harvested.."); } public void plant() { log("Apple has been planted.."); } public static void log(String msg) { System.out.println(msg); } public int getTreeAge() { return treeAge; } public void setTreeAge(int treeAge) { this.treeAge = treeAge; } }
葡萄和草莓和苹果代码几乎一样在这里就不重复了。
园丁类的代码如下(工厂)
public class FruitGardener { public static Fruit factory(String which) throw BadFruitException { if(which.equalsIgnoreCase("apple")) { return new Apple(); } else if(which.equalsIgnoreCase("strawberry")) { return new strawberry(); } else if(which.equalsIgnoreCase("grape")) { return new Grape(); } else { throw new BadFruitException("BadFruitException"); } } }
自我感觉简单工厂模式就是使用which这种生产产品,不存在等级结构。
第十三章 工厂方法
工厂方法模式是类的创建模式,又叫做虚拟构造子模式或者多态工厂模式。
工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中。
同简单工厂模式,在这里给出一个工厂方法的示意图:
源码将在最后给出。
工厂方法模式和简单工厂模式
工厂方法模式和简单工厂模式在结构上的不同时很明显的。工厂方法模式的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。
与简单工厂模式中的情形一样的是,ConcreteCreator的Factory方法返还的数据类型是一个抽象类型Product,而不是哪一个具体的产品类型,而客户端也不必知道所得到的产品的真实类型。这种多态性设计将工厂类选择哪一个产品对象、如何创建这个对象的细节完全封装在具体工厂类内部。
工厂方法模式之所以有一个别名叫做多态性工厂模式,显然是因为具体工厂类都有一个共同的接口,或者都有共同的抽象父类。
如果系统需要加入一个新的产品,那么所需要的就是向系统中加入一个这个产品类以及它所对应的工厂类。没有必要修改客户端,也没有必要修改抽象工厂角色或者其他已有的具体工厂角色。对于增加新的产品类而言,这个系统完全支持开闭原则。
下面是一个工厂方法在农场系统中的实现图:
java语言中工厂方法模式的例子
URL与URLConnection的应用:
package com.javapatterns.factorymethod.url; import java.net.*; import java.io.*; public class URLConnectionReader { public static void main(String[] args) throws Exception { URL yahoo = new URL("http://www.yahoo.com/"); URLConnection yc = yahoo.openConnection(); BufferedReader in = new BufferedReader( new InputStreamReader( yc.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close(); } }
运行时的活动顺序如下:
1.创建一个以http://www.yahoo.com为目标的url对象。
2.调用url对象的openConnection方法,得到一个http://www.yahoo.com的远程连接对象,这个对象的类型是URLConnection。
3.客户端调用URLConnection对象的getInputStream方法读入远程URL的数据。
这个系统在运行时会打印出http://www.yahoo.com主页的全部HTML源代码。
下面是工厂方法的代码:
产品接口:
package com.javapatterns.factorymethod; public interface Product { }
产品1和产品2:
package com.javapatterns.factorymethod; public class ConcreteProduct1 implements Product { public ConcreteProduct1() { System.out.println("CocnreteProduct1 is being created."); } }
package com.javapatterns.factorymethod; public class ConcreteProduct2 implements Product { public ConcreteProduct2() { System.out.println("CocnreteProduct2 is being created."); } }
抽象生产者:
package com.javapatterns.factorymethod; public interface Creator { public Product factory(); /** @link dependency * @label Creates*/ /*# Product lnkProduct; */ }
两个具体的生产者(ConcreteCreator1 ConcreteCreator2):
package com.javapatterns.factorymethod; public class ConcreteCreator1 implements Creator { public Product factory() { return new ConcreteProduct1(); } }
package com.javapatterns.factorymethod; public class ConcreteCreator2 implements Creator { public Product factory() { return new ConcreteProduct2(); } }
客户端:
package com.javapatterns.factorymethod; public class Client { private static Creator creator1, creator2; private static Product prod1, prod2; public static void main(String[] args) { creator1 = new ConcreteCreator1(); prod1 = creator1.factory(); creator2 = new ConcreteCreator2(); prod2 = creator2.factory(); } }
个人感觉工厂方法就是建立和产品一样的等级结构。
第十四章 抽象工厂模式
首先给出抽象工厂模式的简略类图:
左边的等级结构代表工厂等级结构,右边的两个等级结构分别代表两个不同的产品的等级结构。
在什么情况下应当使用抽象的工厂模式
1.一个系统不应该依赖与产品类实例如何被创建,组合和表达的细节,这对于所有形态的工厂模式都是重要的。
2.这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品
3.同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
4.系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
增加新的产品等级结构
在产品族的数目不变的情况下,增加新的产品等级结构。换言之,所有的产品等级结构中的产品数目不会改变,但是现在多出一个与现有的产品等级结构平行的新的产品等级结构。
要做到这一点,就需要修改所有的工厂角色,给每一个工厂类都增加一个新的工厂方法,而这显然是违背开闭原则的。换言之,对于产品等级结构的增加,抽象工厂模式是不支持开闭原则的。
综合起来,抽象工厂模式以一种倾斜的方式支持增加新的产品,它为新产品族的增加提供方便,而不能为新的产品等级结构的增加提供这样的方便。
抽象工厂模式在农场系统中的实现
蔬菜总接口:
package com.javapatterns.abstractfactory.farm; public interface Veggie { }
北方和热带蔬菜:
package com.javapatterns.abstractfactory.farm; public class NorthernVeggie implements Veggie { private String name; public NorthernVeggie(String name) { } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package com.javapatterns.abstractfactory.farm; public class TropicalVeggie implements Veggie { private String name; public TropicalVeggie(String name) { } public String getName() { return name; } public void setName(String name) { this.name = name; } }
水果:
package com.javapatterns.abstractfactory.farm; public interface Fruit { }
北方和热带水果:
package com.javapatterns.abstractfactory.farm; public class NorthernFruit implements Fruit { private String name; public NorthernFruit(String name) { } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package com.javapatterns.abstractfactory.farm; public class TropicalFruit implements Fruit { private String name; public TropicalFruit(String name) { } public String getName() { return name; } public void setName(String name) { this.name = name; } }
园丁接口:
package com.javapatterns.abstractfactory.farm; public interface Gardener { public Fruit createFruit(String name); public Veggie createVeggie(String name); }
北方和热带园丁:
package com.javapatterns.abstractfactory.farm; public class NorthernGardener implements Gardener { public Fruit createFruit(String name) { return new NorthernFruit(name); } public Veggie createVeggie(String name) { return new NorthernVeggie(name); } }
package com.javapatterns.abstractfactory.farm; public class TropicalGardener implements Gardener { public Fruit createFruit(String name) { return new TropicalFruit(name); } public Veggie createVeggie(String name) { return new TropicalVeggie(name); } }
上面代码的设计图如下:
个人理解抽象工厂模式就是对于多个产品族的。这多个产品族的结构相同,生产者的等级结构的每一部分对应生产产品族的一个部分。
发表评论
-
设计模式记录(3.2)
2010-09-08 21:36 758第二十五章 合成模式 合成模型模式属于对象的结构模式, ... -
设计模式记录(3.1)
2010-09-08 13:16 715第四部分 结构模式 第二十二章 适配器模式 适配器模式 ... -
设计模式记录(2.4)
2010-09-06 13:35 784第十二章 原始模型模式 原始模型模式属于对象的创建模式 ... -
设计模式记录(2.3)
2010-09-03 23:20 767第十九章 建造模式 建造模式似乎对象的创建模式。建造模 ... -
设计模式记录(2.2)
2010-09-03 08:30 858第十五章 单例模式 单 ... -
设计模式记录(1)
2010-08-31 19:05 901第四章 开闭原则 开闭原则讲的是:一个软件实体应该对扩展开放, ...
相关推荐
### 设计模式精解——GoF 23种设计模式解析及C++实现源码 #### 引言 设计模式是软件工程领域中一个极为重要的概念,它代表着一系列被广泛接受的解决特定问题的方法。GoF(Gang of Four)所提出的23种设计模式更是...
书名: 设计模式可复用面向对象软件的基础 英文原书名: Design Patterns:Elements of Reusable Object-Oriented software 作者: Erich Gamma 等 译者: 李英军 马晓星 蔡敏 刘建中 书号: 7-111-07575-7 页码: 254 定价...
我们并不认为这组设计模式是完整的和一成不变的,它只是我们目前对设计的思考的记录。因此我们欢迎广大读者的批评与指正,无论从书中采用的实例、参考,还是我们遗漏的已知应用,或应该包含的设计模式等方面。你...
设计模式的学习和应用分为几个阶段:首先自己学会设计模式,然后将其转化为自己的语言表达出来,接着是教授他人并最终记录下来。这种学习路径要求学习者不仅要理解设计模式本身,还要具备清晰的表达能力和深刻的理解...
### 设计模式精解——GoF 23种设计模式解析及C++实现源码 #### 0. 引言 设计模式是软件工程领域的一个重要概念,它为解决特定问题提供了一套标准的解决方案。《设计模式精解——GoF 23种设计模式解析及C++实现源码...
### Java设计模式的应用 #### 一、引言 在当今快速发展的软件开发领域,Java作为一门功能强大且灵活的语言,不仅拥有丰富的API资源,还能与强大的数据库系统无缝对接。这使得许多开发人员能够以模块化的形式构建...
### 设计模式精解——GoF 23种设计模式解析及C++实现源码 #### 0. 引言 ##### 0.1 设计模式解析(总序) 设计模式是面向对象编程中用于解决常见问题的一系列模板。它们为软件设计提供了标准化的解决方案,帮助...
本书设计实例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。本书分类描述了一组设计良好,表达清楚的软件设计模式,这些模式在实用环境下有特别有用...
### 设计模式精解—GoF 23种设计模式解析及C++实现源码 #### 0. 引言 设计模式作为一种重要的面向对象设计工具,在软件开发中扮演着至关重要的角色。本文旨在深入解析GoF(Gang of Four,四人组)提出的23种设计...
根据给定的信息,本文将深入探讨GoF23种设计模式的核心概念及其应用场景,并通过具体的实例来解析每一种设计模式的实现原理和技术要点。 ### 0. 引言 设计模式是一系列被广泛接受的解决方案,用于解决软件设计中...
1.1 什么是设计模式 2 1.2 Smalltalk MVC中的设计模式 3 1.3 描述设计模式 4 1.4 设计模式的编目 5 1.5 组织编目 7 1.6 设计模式怎样解决设计问题 8 1.6.1 寻找合适的对象 8 1.6.2 决定对象的粒度 9 1.6.3 指定对象...
《C++设计模式精解与代码实现:GoF23种设计模式的深入解析》 在软件工程领域,设计模式被视为解决特定问题的最佳实践,它不仅能够提高代码的可读性和可维护性,还能增强软件的灵活性和扩展性。本文旨在深入解析由...
《设计模式精解-GoF23种设计模式解析附C实现源码》这份资料深入浅出地介绍了软件工程领域著名的“Gang of Four”(GoF)所提出的23种设计模式,不仅提供了理论上的解析,还附带了具体的C语言实现源码,为读者提供了...
1.1 什么是设计模式 2 1.2 Smalltalk MVC中的设计模式 3 1.3 描述设计模式 4 1.4 设计模式的编目 5 1.5 组织编目 7 1.6 设计模式怎样解决设计问题 8 1.6.1 寻找合适的对象 8 1.6.2 决定对象的粒度 9 1.6.3 指定对象...