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 存储配置
- Django学习---组合搜索组件
组合搜索组件 我们都会写博客,写文章之后我们要给文章设置目录,设置类型.之后我们在浏览文章的时候就能够按类别进行精确定位到文章,那这个组合搜索我们应该怎么做呢? 首先我们先创建3张表,分别存放文章,文 ...
- module.exports 、exports、export、export default的区别
module.exports和exports是属于 CommonJS 模块规范,export和export default是属于ES6语法. module.exports和exports导出模块,用r ...
- 778. Swim in Rising Water
▶ 给定方阵 grid,其元素的值为 D0n-1,代表网格中该点处的高度.现在网格中开始积水,时刻 t 的时候所有值不大于 t 的格点被水淹没,当两个相邻格点(上下左右四个方向)的值都不超过 t 的时 ...
- 关于SSE的一些资料
之前查到的,觉得还不错,一直没时间看,放这里先存着 https://software.intel.com/en-us/articles/using-intel-streaming-simd-exten ...
- oracle执行sql文件
oracle执行sql文件 在PL/SQL中直接用command window执行就可以了: PL/SQL developer----->File------>New---->com ...
- ORA-12528问题解决
这个问题说明数据库没有Mount 最好先将系统日志一并清空,避免以下报错信息: ERROR:ORA-28056: Writing audit records to Windows Event Log ...
- java web 开发 IDE 下载地址
https://www.eclipse.org/downloads/eclipse-packages/
- 19.Remove Nth Node From End of List(List; Two-Pointers)
Given a linked list, remove the nth node from the end of list and return its head. For example, Give ...
- 使用 ipmitool 实现 Linux 系统下对服务器的 ipmi 管理
http://www.ibm.com/developerworks/cn/linux/l-ipmi/ 1.简介 IPMI(Intelligent Platform Management Interfa ...