本文从简单工厂模式的缺点说起,引入工厂方法模式,介绍的工厂方法模式的基本知识,实现要点和应用场景,最后举例进行说明工厂方法模式的应用。
在之前的《Javascript设计模式理论与实战:简单工厂模式》这篇文章中,我们介绍了简单工厂的知识和一些应用。简单工厂模式存在一个唯一的工厂类,它的优点是所有产品类的实例化集中管理,便于理解,但这既是优点也是缺点。如果
产品类的数量较少并且不会经常发生变化,我们可以直接利用简单工厂模式,但是有的时候,需求是随时在变的,产品类也可能随时在增加,如果使用简单工厂模式,就不可避免的要去修改工厂类的代码。要解决这个问题,就要提到今天要说的工厂方法模式。

基本概念

工厂方法模式:不再有一个唯一的工厂类就创建产品,而是将不同的产品交给对应的工厂子类去实现。每个产品由负责生产的子工厂来创造。如果添加新的产品,需要做的是添加新的子工厂和产品,而不需要修改其他的工厂代码。

工厂方法模式主要有三种类组成:
1.抽象工厂类:负责定义创建产品的公共接口。
2.产品子工厂:继承抽象工厂类,实现抽象工厂类提供的接口
3.每一种产品各自的产品类

工厂方法模式的实现

首先,我们对《Javascript设计模式理论与实战:简单工厂模式》一文中简单工厂模式的代码进行改造。下面是简单工厂公式的代码:

 var productEnums = {
flight: "flight",
hotel: "hotel"
};
function Flight() {
console.log("This is Flight");
}
function Hotel() {
console.log("This is Hotel");
}
var productFactory = (function () {
var productFactories = {
"flight": function () {
return new Flight();
},
"hotel": function () {
return new Hotel();
}
}; return {
createProduct: function (productType) {
return productFactories[productType]();
}
}
})();
function User() {
this.shopCart = [];
}
User.prototype = {
constructor: User,
order: function (productType) {
this.shopCart.push(productFactory.createProduct(productType));
}
}

要将上面的代码修改成工厂方法模式,首先要构造一个抽象工厂类。在JS中,由于我们抽象类的概念,我们无法做到像Java,C#的抽象工厂类,但是我们可以去模拟它。代码如下

 function AbstractFactory() {
}
AbstractFactory.prototype.createProduct = function () {
throw "没有实现该方法";
}

在这段代码中,定义了一个工厂类,然后定义了它的一个方法CreateProduct,这个方法模拟抽象方法,不提供具体实现,而是抛出错误,继承的工厂类就要去实现具体方法,否则会抛错,这就模拟了一个抽象工厂类。
定义完抽象工厂类后,现在我们要做的就是定义子工厂去实现它,我们分别定义两个子工厂FlightFactory和HotelFactory。

 function FlightFactory() {
AbstractFactory.call(this);
}
FlightFactory.prototype = new AbstractFactory();
FlightFactory.prototype.createProduct = function () {
return new Flight();
}
function HotelFactory() {
AbstractFactory.call(this);
}
HotelFactory.prototype = new AbstractFactory();
HotelFactory.prototype.createProduct = function () {
return new Hotel();
}

以上代码分别定义了两个子工厂类,每个子类继承抽象工厂类,然后实现createProduct方法,每一种产品在各自的工厂类里创建。
在客户端怎么调用呢?

 var factory = new FlightFactory();
factory.createProduct();
factory = new HotelFactory();
factory.createProduct();

疑点解答

首先我们要理解一个概念:开放封闭原则。
软件实体应该是可扩展但不可修改的,就是对扩展是开放但是对修改是封闭的。体现在两个方面:
(1)对扩展开放,产品有新需求或变活时,可以对现有代码进行扩展,以适应新变化
(2)对修改封闭,类一旦设计完成,就不应该对其进行修改。

下面来说说几个疑点
1、相比于简单工厂模式,工厂方法模式增多了一个抽象工厂类和多个子工厂类,这样代码不是更复杂了吗?
确实,代码比简单工厂模式复杂了,引入了抽象层,还有子工厂,这会增加代码的复杂度和理解难度。但是相比于简单工厂模式,代码的维护性和扩展性提高了,新增产品时,只需要增加对应的产品类和产品工厂类,不需要修改到抽象工厂类和其他子工厂。更加符合面向对象的开放封闭原则。
当然具体场景具体分析,复杂性和扩展性相比如何舍去,在使用的时候要结合实际场景去分析。
2、在客户端调用的时候,每一种产品还是需要知道具体的工厂类来调用,好像区别不大?
和简单工厂模式的区别在于:我们将判断使用哪一个产品类的代码从工厂类转移到了调用的客户端这里,如果有新功能要添加,我们要修改的是客户端的代码而不是工厂类的代码,这样才符合开放封闭原则。

总结

实现要点

在JS中,我们实现工厂方法模式主要包括3个角色:
1.抽象工厂类:提供工厂方法的声明
2.子工厂类:实现抽象工厂类的工厂方法
3.产品类:具体的产品类

优缺点

优点:克服了简单工厂模式的缺点。如果需要增加新的产品类,无须修改现有系统,只需要增加新的工厂类和产品类;每个工厂类封装了产品对象的创建细节,系统具有良好的灵活性和可扩展性。
缺点:增加新产品的同时需要增加新的工厂,导致系统类的个数成对增加,在一定程度上增加了系统的复杂性。

原文地址:http://luopq.com/2015/11/10/design-pattern-factory-method/

Javascript设计模式理论与实战:工厂方法模式的更多相关文章

  1. Javascript设计模式理论与实战:桥接模式

    桥接模式将抽象部分与实现部分分离开来,使两者都可以独立的变化,并且可以一起和谐地工作.抽象部分和实现部分都可以独立的变化而不会互相影响,降低了代码的耦合性,提高了代码的扩展性. 基本理论 桥接模式定义 ...

  2. Javascript设计模式理论与实战:状态模式

    在软件开发中,很大部分时候就是操作数据,而不同数据下展示的结果我们将其抽象出来称为状态,我们平时开发时本质上就是对应用程序的各种状态进行切换并作出相应处理.状态模式就是一种适合多种状态场景下的设计模式 ...

  3. Javascript设计模式理论与实战:组合模式

    我们平时开发过程中,一定会遇到这种情况:同时处理简单对象和由简单对象组成的复杂对象,这些简单对象和复杂对象会组合成树形结构,在客户端对其处理的时候要保持一致性.比如电商网站中的产品订单,每一张产品订单 ...

  4. 前端读者 | Javascript设计模式理论与实战:状态模式

    本文来自 @狼狼的蓝胖子:链接:http://luopq.com/2015/11/25/design-pattern-state/ 在软件开发中,很大部分时候就是操作数据,而不同数据下展示的结果我们将 ...

  5. Java设计模式(二) 工厂方法模式

    本文介绍了工厂方法模式的概念,优缺点,实现方式,UML类图,并介绍了工厂方法(未)遵循的OOP原则 原创文章.同步自作者个人博客 http://www.jasongj.com/design_patte ...

  6. 重学 Java 设计模式:实战工厂方法模式

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!

  7. Java设计模式学习笔记(三) 工厂方法模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 简介 上一篇博客介绍了简单工厂模式,简单工厂模式存在一个很严重的问题: 就是当系统需要引入 ...

  8. 设计模式(三)工厂方法模式(Factory Pattern)

    一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是——简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...

  9. 设计模式(2)工厂方法模式(Factory Method)

    设计模式(0)简单工厂模式 设计模式(1)单例模式(Singleton) 源码地址 0 工厂方法模式简介 0.0 工厂方法模式定义 工厂方法模式是在简单工厂模式基础上,为解决更复杂的对象创建问题而衍生 ...

随机推荐

  1. python + docker, 实现天气数据 从FTP获取以及持久化(一)

    前情提要 最近项目需要天气数据(预报和历史数据)来作为算法程序的输入. 项目的甲方已经购买了天气数据, 依照他们的约定,天气数据的供应商会将数据以"文本" (.TXT)的方式发到F ...

  2. ubuntu 下出现E: Sub-process /usr/bin/dpkg returned an error code

    在用apt-get安装软件时出现了类似于 install-info: No dir file specified; try –help for more information.dpkg:处理 get ...

  3. jquery内容补充

    jquery除了咱们上面讲解的常用知识点之外,还有jquery 插件.jqueryUI知识点 jqueryUI 官网: https://jqueryui.com/ jqueryUI 中文网: http ...

  4. nodejs连接mongodb

    一.安装 a.访问mongodb官网下载https://www.mongodb.com/,有zip或者msi版本,zip解压缩就可以用,msi需要安装后使用 b.安装,指定好安装路径,一路下一步 c. ...

  5. eclipse 创建dynamic web project不能运行

    按照李刚<轻量级java ee企业应用实战>第三版,第二章的配置,发现eclipse 创建dynamic web project不能运行,原来作者第二章时还不是在eclipse中开发的,只 ...

  6. 用WINSOCK API实现同步非阻塞方式的网络通讯

    Option Base 0Option Explicit '* ************************************************** *'*  模块名称:Winsock ...

  7. 我的Linux之路——windows10用WMware安装CentOS7.5 虚拟机详细步骤

    出自:https://www.jianshu.com/p/99f784d465f4 VMware简介:   VMware是一个虚拟PC的软件,可以在现有的操纵系统上虚拟出一个新的硬件环境,相当于模拟出 ...

  8. U3D屏幕坐标,世界坐标,像素坐标之间的关系

    U3D中,屏幕坐标和世界坐标单位一样,二者之间是直接的一一对应关系,不受屏幕分辨率影响.默认情况下屏幕空间画布的左下角坐标是世界原点(0,0,0),这种情形下,世界空间的点(1920,1080,任何值 ...

  9. NGUI中显示DrawCall详细信息

    [NGUI显示DrawCall详细信息] UIDrawCall中有个宏,SHOW_HIDDEN_OBJECTS,默认为关闭状态.将此宏打开,NGUI即会将DrawCall对象显示在Hierarchy中 ...

  10. 在制MO未取到FP

    原因:今天在制MO未取进去原因为业务人员维护验货客户尾缀时维护ZZ导致,需更新为C开头即可 SELECT * FROM IN_SFCHEADER WHERE MO_ID in('00110051832 ...