《Java设计模式及实践》—2.2 工厂模式

举报
华章计算机 发表于 2019/07/22 12:13:45 2019/07/22
【摘要】 本节书摘来自华章计算机《Java设计模式及实践》一书中的第2章,第2.2.1节,[印度] 卡马尔米特·辛格(Kamalmeet Singh)[荷兰] 艾德里安·伊恩库列斯库(Adrian Ianculescu) 著[罗马尼亚] 路西安-保罗·托尔耶(Lucian-Paul Torje) 张小坤 黄 凯 贺 涛 译.

2.2 工厂模式

正如前面章节所描述,在面向对象编程中,继承是一个基本概念,它与多态共同构成了类的父子继承关系(Is-A关系)。Car对象可以被当作Vehicle对象处理,Truck对象也可以被当作Vehicle对象处理。一方面,这种抽象方式使得同一段代码能为Car和Truck对象提供同样的处理操作,使代码更加简洁;另一方面,如果要扩展新的Vehicle对象类型,比如Bike或Van,不再需要修改代码,只需添加新的类即可。

在大多数情况下,最棘手的问题往往是对象的创建。在面向对象编程中,每个对象都使用特定类的构造器进行实例化操作,如下面代码所示:

 image.png

这段代码说明了Vehicle和Car两个类之间的依赖关系。这样的依赖关系使代码紧密耦合,在不更改的情况下很难扩展。举例来说,假设要用Truck替换Car,就需要修改相应的代码:

 image.png

这里存在两个问题:其一,类应该保持对扩展的开放和对修改的关闭(开闭原则);其二,每个类应该只有一个发生变化的原因(单一职责原则)。每增加新的类造成主要代码修改时会打破开闭原则,而主类除了其固有功能之外还负责实例化vehicle对象,这种行为将会打破单一职责原则。

在这种情况下就需要一种更好的设计方案。我们可以增加一个新类来负责实例化vehicle对象,称之为简单工厂模式。

2.2.1 简单工厂模式

工厂模式用于实现逻辑的封装,并通过公共的接口提供对象的实例化服务,在添加新的类时只需要做少量的修改。

简单工厂的实现描述如图2-2所示。

类SimpleFactory中包含实例化ConcreteProduct 1和ConcreteProduct 2的代码。当

客户需要对象时,调用SimpleFactory的createProduct()方法,并提供参数指明所需对象的类型。SimpleFactory实例化相应的具体产品并返回,返回的产品对象被转换为基类类型。因此,无论是ConcreteProduct 1还是ConcreteProduct 2,客户能以相同的方式处理。

 image.png

图 2-2

1.静态工厂模式

下面我们写一个简单的工厂类用来创建Vehicle实例。我们创建一个抽象Vehicle类和继承自它的三个具体类:Bike、Car和Truck。工厂类(也叫静态工厂类)代码如下所示:

 image.png

 

工厂类逻辑非常简单,只负责Vehicle类的实例化,符合单一职责原则;用户只调用Vehicle接口,这样做可以减少耦合,符合依赖倒置原则;但是当增加一个新的Vehicle类时,需要对VehicleFactory类进行修改,这样就打破了开闭原则。

我们可以改进这种简单工厂模式,使得注册的新类在使用时才被实例化,从而保证其对扩展开放,同时对修改闭合。

具体的实现方式有以下两种:

  • 使用反射机制注册产品类对象和实例化。

  • 注册产品对象并向每个产品添加newInstance方法,该方法返回与自身类型相同的新实例。

2.使用反射机制进行类注册的简单工厂模式

为此,我们需要使用map对象来保存产品ID及其对应的类:

 image.png

然后,增加一个注册新Vehicle类的方法:

 image.png

构造方法如下所示:

 image.png

但在某些情况下,反射机制并不适用。比如,反射机制需要运行时权限,这在某些特定环境中是无法实现的。反射机制也会降低程序的运行效率,在对性能要求很高的场景下应该避免使用这种机制。

3.使用newInstance方法进行类注册的简单工厂模式

前面的代码中使用了反射机制来实现新Vehicle类的实例化。如果要避免使用反射机制,可以使用注册新Vehicle类的类似工厂类,不再将类添加到map对象中,而是将要注册的每种对象实例添加其中。每个产品类都能够创建自己的实例。

首先在Vehicle基类中添加一个抽象方法:

 image.png

对于每种产品,基类中声明为抽象的方法都要实现:

 image.png

在工厂类中,更改map用于保存对象的ID及其对应的Vehicle对象:

 image.png

通过实例注册一种新的Vehicle类型:

 image.png

也要相应地改变createVehicle方法:

image.png

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。