工厂方法模式

8.1 女娲造人的故事

东汉《风俗通》记录了一则神话故事:“开天辟辟,未有人民,女娲搏,黄土作人……”,讲述的内容就是大家非常熟悉的女娲造人的故事。开天辟地之初,大地上并没有生物,只有苍茫大地,纯粹而洁净的自然环境,寂静而又寂寞,于是女娲决定创造一个新物种(即人类)来增加世界的繁荣,怎么制造呢?

别忘了女娲是神仙,没有办不到的事情,造人的过程是这样的:首先,女娲采集黄土捏成人的形状,然后放到八卦炉中烧制,最后放置到大地上生长,工艺过程是没有错的,但是意外随时都会发生:

第一次烤泥人,兹兹兹兹,感觉应该熟了,往大地上一放,哇,没烤熟!于是一个白人诞生了!(这也是缺乏经验的最好证明)

第二次烤泥人,兹兹兹兹兹兹兹兹,上一次没烤熟,这次多烤一会儿,放到世间一看,嘿,熟过头了,于是黑人诞生了!

第三次烤泥人,兹~~兹~~兹~~,一边烧制一边察看,直到表皮微黄,嘿,真正好,于是黄色人种出现了!

这个造人过程是比较有意思的,是不是可以通过软件开发来实现这个过程呢?古人云“三人行,必有我师焉”,在面向对象的思维中,万物皆对象,是对象我们就可以通过软件设计来实现。首先对造人过程进行分析,该过程涉及三个对象:女娲、八卦炉、三种不同肤色的人,女娲可以使用场景类Client来表示,八卦炉类似于一个工厂,负责制造生产产品(即人类):三种不同肤色的人,他们都是同一个接口下的不同实现类,都是人嘛,只是肤色、语言不同,对于八卦炉来说都是它生产出的产品。分析完毕,我们就可以画出如图8-1所示类图。

图8-1 女娲造人类图

类图比较简单,AbstractHumanFactory是一个抽象类,定义了一个八卦炉都具有的整体功能,HumanFactory为实现类,完成具体的任务:创建人类;Human接口是人类的总称,其三个实现类分别为三类人种;NvWa类是一个场景类,负责模拟这个场景,执行相关的任务。

我们定义的每个人种都有两个方法:getColor(获得人的皮肤颜色)和talk(交谈),其源代码如代码清单8-1所示。

代码清单8-1 人类总称

1
2
3
4
5
6
7
8
9
10
11
public interface Human {
 
//每个人种的皮肤都有相应的颜色
 
public void getColor();
 
//人类会说话
 
public void talk();
 
}

接口Human是对人类的总称,每个人种都至少具有两个方法,黑色人种、黄色人种、白色人种的代码分别如代码清单8-2、8-3、8-4所示。

代码清单8-2 黑色人种

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class BlackHuman implements Human {
 
public void getColor(){
 
System.out.println("黑色人种的皮肤颜色是黑色的!");
 
}
 
public void talk() {
 
System.out.println("黑人会说话,一般人听不懂。");
 
}
 
}

代码清单8-3 黄色人种

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class YellowHuman implements Human {
 
public void getColor(){
 
System.out.println("黄色人种的皮肤颜色是黄色的!");
 
}
 
public void talk() {
 
System.out.println("黄色人种会说话,一般说的都是双字节。");
 
}
 
}

代码清单8-4 白色人种

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class WhiteHuman implements Human {
 
public void getColor(){
 
System.out.println("白色人种的皮肤颜色是白色的!");
 
}
 
public void talk() {
 
System.out.println("白色人种会说话,一般都是但是单字节。");
 
}
 
}

所有的人种定义完毕,下一步就是定义一个八卦炉,然后烧制人类。我们想象一下,女娲最可能给八卦炉下达什么样的生产命令呢?应该是“给我生产出一个黄色人种(YellowHuman类)”,而不会是“给我生产一个会走、会跑、会说话、皮肤是黄色的人种”,因为这样的命令增加了交流的成本,作为一个生产的管理者,只要知道生产什么就可以了,而不需要事物的具体信息。通过分析,我们发现八卦炉生产人类的方法输入参数类型应该是Human接口的实现类,这也解释了为什么类图上的AbstractHumanFactory抽象类中createHuman方法的参数为Class类型。其源代码如代码清单8-5所示。

代码清单8-5 抽象人类创建工厂

1
2
3
4
5
public abstract class AbstractHumanFactory {
 
public abstract Human createHuman(Class<? extends Human> c);
 
}

注意,我们在这里采用了JDK 1.5的新特性:泛型(Generic),通过定义泛型对createHuman的输入参数产生两层限制:

  • 必须是Class类型;
  • 必须是Human的实现类;

其中的“?”表示的是,只要实现了Human接口的类都可以作为参数,泛型是JDK 1.5中的一个非常重要的新特性,它减少了对象间的转换,约束其输入参数类型,对Collection集合下的实现类都可以定义泛型。有关泛型详细知识,请参考相关的Java语法文档。

目前女娲只有一个八卦炉,其实现了生产人类的方法,如代码清单8-6所示。

代码清单8-6 人类创建工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class HumanFactory extends AbstractHumanFactory {
 
public Human createHuman(Class<? extends Human> c){
 
//定义一个生产的人种
 
Human human=null;
 
try {
 
//产生一个人种
 
human = (Human)Class.forName(c.getName()).newInstance();
 
} catch (Exception e) {
 
System.out.println("人种生成错误!");
 
}
 
return human;
 
}
 
}

人种有了,八卦炉也有了,剩下的工作就是女娲采集黄土,然后命令八卦炉开始生产,其过程如代码清单8-7所示。

代码清单8-7 女娲类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class NvWa {
 
public static void main(String[] args) {
 
//声明阴阳八卦炉
 
AbstractHumanFactory YinYangLu = new HumanFactory();
 
//女娲第一次造人,火候不足,缺陷产品
 
System.out.println("--造出的第一批人是白色人种--");
 
Human whiteHuman = YinYangLu.createHuman(WhiteHuman.class);
 
whiteHuman.getColor();
 
whiteHuman.talk();
 
//女娲第二次造人,火候过足,又是次品,
 
System.out.println("\n--造出的第二批人是黑色人种--");
 
Human blackHuman = YinYangLu.createHuman(BlackHuman.class);
 
blackHuman.getColor();
 
blackHuman.talk();
 
//第三次造人,火候刚刚好,优品!黄色人种
 
System.out.println("\n--造出的第三批人是黄色人种--");
 
Human yellowHuman = YinYangLu.createHuman(YellowHuman.class);
 
yellowHuman.getColor();
 
yellowHuman.talk();
 
}
 
}

设计模式之java源码-工厂方法模式的更多相关文章

  1. 设计模式(Java语言)- 工厂方法模式

    前言 在介绍工厂方法模式之前,我们需要知道这个设计模式是什么,解决了什么样的问题?在上一篇博客 设计模式(Java语言)- 简单工厂模式 介绍了简单工厂模式,然后总结了简单工厂模式的缺点: 1.当新增 ...

  2. 设计模式之第1章-工厂方法模式(Java实现)

    设计模式之第1章-工厂方法模式(Java实现) “我先来”,“不,老公,我先!”.远远的就听到几个人,哦不,是工厂方法模式和抽象工厂模式俩小夫妻在争吵,尼妹,又不是吃东西,谁先来不都一样(吃货的世界~ ...

  3. Javascript设计模式理论与实战:工厂方法模式

    本文从简单工厂模式的缺点说起,引入工厂方法模式,介绍的工厂方法模式的基本知识,实现要点和应用场景,最后举例进行说明工厂方法模式的应用.在之前的<Javascript设计模式理论与实战:简单工厂模 ...

  4. .NET设计模式(5):工厂方法模式(Factory Method)(转)

    工厂方法模式(Factory Method) ——.NET设计模式系列之五 Terrylee,2004年1月2日 概述 在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的具体实 ...

  5. .NET设计模式(5):工厂方法模式(Factory Method)

    ):工厂方法模式(Factory Method)    工厂方法模式(Factory Method) --.NET设计模式系列之五 Terrylee,2004年1月2日 转载:http://terry ...

  6. 设计模式04: Factory Methord 工厂方法模式(创建型模式)

    Factory Methord 工厂方法模式(创建型模式) 从耦合关系谈起耦合关系直接决定着软件面对变化时的行为 -模块与模块之间的紧耦合使得软件面对变化时,相关的模块都要随之变更 -模块与模块之间的 ...

  7. JAVA中的工厂方法模式和抽象工厂模式

    工厂方法模式: 定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类.类型:创建类模式类图: 类图知识点:1.类图分为三部分,依次是类名.属性.方法2.以& ...

  8. C#设计模式学习笔记:(2)工厂方法模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7567880.html,记录一下学习过程以备后续查用. 一.引言 接上一篇C#设计模式学习笔记:简单工厂模式( ...

  9. 设计模式总结篇系列:工厂方法模式(Factory Method)

    工厂方法模式适合于对实现了同一接口或继承了同一父类的一些类进行实例的创建.一般是通过定义一个工厂类,并在其方法中实现对具有上述特点的类对象的创建. 根据具体产生类对象的方法定义形式,又可以将其分为普通 ...

随机推荐

  1. tornado-通过判断后台数据限制登陆--简单的

    import tornado.ioloop import tornado.web import tornado.httpserver # 非阻塞 import tornado.options # 提供 ...

  2. OpenACC 计算规约时发现的小坑

    ▶ 使用 OpenACC 的 parallel 构件来计算规约,主要想说的是 win10 pgi 和 win10 WSL pgi 结果的不同和关于 for 循环的一个小坑 ● 正常的代码 #inclu ...

  3. Mysql 2条记录 差值计算

    1 表结构 2:  其实 是2个相同的 表根据rownum= rownum-1 来计算,所以先了解单个表的查询 附上SQL: #查询出1天的数据升序 ) as rownum, info.equipme ...

  4. AS3 巧用事件api简化鼠标拖动流程

     拖动,按照一般人的定义,拖动就是鼠标按下的时候移动鼠标,这里面有三个过程,分别是按下.移动鼠标和弹起.以stage为例,大家的实现步骤通常如下:(PS:此处不讨论startDrag和stopDrag ...

  5. MySQL JSON 类型数据操作

    1.Java 中动态扩展字段,会导致数据库表被锁,在MySQL 5.7.8版本之前,因为MySQL不能直接操作JSON类型数据,可以将一个字段设定成varchar类型,里面存放JSON格式数据,这样在 ...

  6. windows10配置java开发环境

    一.下载jdk 二.安装jdk路径,这个路径不能包含中文名 三.系统会提示安装jre,安装目录不要是jdk的安装目录,否则会覆盖掉jdk目录下的jre目录 四. .;%JAVA_HOME%\lib;% ...

  7. mysql case, if

    if语句: 用法和excel的if函数很像 if(expr1, value_if_expr1_is_true, value_if_expr1_is_false) select if(tag = 3, ...

  8. C++11中std::forward的使用 (转)

    std::forward argument: Returns an rvalue reference to arg if arg is not an lvalue reference; If arg ...

  9. 重学Java

    Java web 的课程告一段落了 现在我觉得我应该重新学习一下 Java基础  先分享下昨天学习递归后写的两个短短的代码 1.求5的阶乘 package test; public class fiv ...

  10. MVC3 发布到IIS 7.5

    1.应用程序池采用集成模式(建议),.NET Framework版本为: .NET Framework4.0.30319. 2.确保ASP.NET MVC3已安装好,然后检查站点的处理程序映射,看是否 ...