Javascript设计模式理论与实战:工厂方法模式
本文从简单工厂模式的缺点说起,引入工厂方法模式,介绍的工厂方法模式的基本知识,实现要点和应用场景,最后举例进行说明工厂方法模式的应用。
在之前的《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设计模式理论与实战:工厂方法模式的更多相关文章
- Javascript设计模式理论与实战:桥接模式
桥接模式将抽象部分与实现部分分离开来,使两者都可以独立的变化,并且可以一起和谐地工作.抽象部分和实现部分都可以独立的变化而不会互相影响,降低了代码的耦合性,提高了代码的扩展性. 基本理论 桥接模式定义 ...
- Javascript设计模式理论与实战:状态模式
在软件开发中,很大部分时候就是操作数据,而不同数据下展示的结果我们将其抽象出来称为状态,我们平时开发时本质上就是对应用程序的各种状态进行切换并作出相应处理.状态模式就是一种适合多种状态场景下的设计模式 ...
- Javascript设计模式理论与实战:组合模式
我们平时开发过程中,一定会遇到这种情况:同时处理简单对象和由简单对象组成的复杂对象,这些简单对象和复杂对象会组合成树形结构,在客户端对其处理的时候要保持一致性.比如电商网站中的产品订单,每一张产品订单 ...
- 前端读者 | Javascript设计模式理论与实战:状态模式
本文来自 @狼狼的蓝胖子:链接:http://luopq.com/2015/11/25/design-pattern-state/ 在软件开发中,很大部分时候就是操作数据,而不同数据下展示的结果我们将 ...
- Java设计模式(二) 工厂方法模式
本文介绍了工厂方法模式的概念,优缺点,实现方式,UML类图,并介绍了工厂方法(未)遵循的OOP原则 原创文章.同步自作者个人博客 http://www.jasongj.com/design_patte ...
- 重学 Java 设计模式:实战工厂方法模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!
- Java设计模式学习笔记(三) 工厂方法模式
前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 简介 上一篇博客介绍了简单工厂模式,简单工厂模式存在一个很严重的问题: 就是当系统需要引入 ...
- 设计模式(三)工厂方法模式(Factory Pattern)
一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是——简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...
- 设计模式(2)工厂方法模式(Factory Method)
设计模式(0)简单工厂模式 设计模式(1)单例模式(Singleton) 源码地址 0 工厂方法模式简介 0.0 工厂方法模式定义 工厂方法模式是在简单工厂模式基础上,为解决更复杂的对象创建问题而衍生 ...
随机推荐
- mysql错误:Can’t create TCP/IP socket (10106) 解决方法
错误描述 “mysql错误:Can’t create TCP/IP socket (10106)”,目测是socket端口被占用的原因,然后在打开tomcat,报的错误中也包含了“socket”,再一 ...
- PHP CRC16 校验码的算法怎么使用
PHP CRC16 校验码的算法如何使用最近用到CRC16, 我现在就是要把 010301180001 算出CRC16的校验码,通过其他工具,可以得到 校验码是 05F1 最后完整的代码就是 0103 ...
- 基于指纹考勤机的真实的PHP操作Access数据库成功案例(最终实现) 2011-11-2v
听了我的建议,我们单位的食堂准备使用一台指纹考勤机统计吃饭人次,这样院里好给食堂的承包人以相应饭补.以前买过一台彩屏指纹机,数据库是access的,今儿又买了一台准备放到食堂里,而且考虑到停电,还特地 ...
- Unreal Enginer4特性介绍
转自:http://blog.csdn.net/cartzhang/article/details/39401991 一.特性说明 特性 Ue4是一款专业开发高质量游戏的平台开发工具.Ue4的渲染加快 ...
- Sql Server-使用Sql Server自带的分词功能实现字段关键词提取(分词能力很低,慎用)
“创建全文索引 启动服务 在SQL Server配置管理工具中,找到'SQL Full-text Filter Daemon Launcher'服务用本地用户启动. 创建全文目录 打开需要创建全文目录 ...
- Java下LDAP操作的资料
话说LDAP真是个诡异的protocol(或者数据库,或者服务,whatever...),没有一个特别形象的spec.这里列出一些筛选出的还可以的文档,都是oracle的: https://docs. ...
- ASP.NET中的几种弹出框提示基本实现方法
我们在.NET程序的开发过程中,常常需要和用户进行信息交互,比如执行某项操作是否成功,“确定”还是“取消”,以及选择“确定”或“取消”后是否需要跳转到某个页面等,下面是本人对常用对话框使用的小结,希望 ...
- PL/SQL Developer Initialization erro
PL/SQL Developer---------------------------Initialization errorSQL*Net not properly installed Oracle ...
- JDK动态代理代码示例
JDK动态代理代码示例 业务接口 实现了业务接口的业务类 实现了InvocationHandler接口的handler代理类 1.业务接口 package com.wzq.demo01; /** * ...
- javascript 对象的扩展性
javascript 对象 的可扩展性 javascript 对象中的可扩展性指的是:是否可以给对象添加新属性.所有的内置对象和自定义对象显示的都是可扩展的,对于宿主对象,则有javascript 引 ...