JS 设计模式之:工厂模式定义与实现方法浅析


Posted in Javascript onMay 06, 2020

本文实例讲述了JS 设计模式之:工厂模式定义与实现方法。分享给大家供大家参考,具体如下:

前言

上次我们介绍了单例模式,没看过的小伙伴可以看这个链接:

浅析 JS 设计模式之:单例模式

今天来说一说一种常见的设计模式:工厂模式。

工厂模式是一种创建对象的 创建型模式,遵循 DRY(Don't Repeat Yourself)原则。在该模式下,代码将会根据具体的输入或其他既定规则,自行决定创建哪种类型的对象。简单点儿说就是,动态返回需要的实例对象

回顾上次的例子

让我们继续使用单例模式中的例子,一个日志工具 Logger :

class Logger {
 log (...args) {
  console.log(...args);
 }
}

上面是最核心的 api,每次使用都需要使用 new Logger() 来创建一个 logger 对象,然后使用方法就和 console 一样啦~

多种 Logger

假如我们现在的代码要支持 electron 环境,即日志既可以是 console 日志,也可以是 file 日志,那么我们就需要有两种类型的 logger:

ConsoleLogger

// logger/console.js
class ConsoleLogger {
 log (...args) {
  console.log(...args)
 }
}
export default ConsoleLogger

FileLogger

// logger/file.js
class FileLogger {
 log (...args) {
  dumpLog(...args)
 }
}
export default FileLogger

这里先不用管 dumpLog 的具体实现,只用知道它就是将日志写在文件中的即可~

使用工厂

我们已经有了两种类型的 logger,但是这两种 logger 的 api 实际上都是一样的,在项目中直接导入当然也可以使用,只不过每次都要导入对应类型的模块,然后再使用,像下面这样:

使用 console logger

import ConsoleLogger from './logger/console'
const logger = new ConsoleLogger()

使用 file logger

import FileLogger from './logger/file'
const logger = new FileLogger()

是不是很繁琐?如果还有其他 logger 类型,如远程日志,就会出现更多种使用方式了。为了把 logger 模块的使用方式统一,这时候就会用到工厂模式啦~

让我们新建一个 index.js

// logger/index.js
import ConsoleLogger from './console.js'
import FileLogger from './file.js'

function createLogger(type = 'console') {
 if (type === 'console') {
  return new ConsoleLogger()
 } else if (type === 'file') {
  return new FileLogger()
 }
 throw new Error(`Logger type not found: ${type}`)
}

export default createLogger

好了,这下我们的使用方式就会变成这样:

import createLogger from './logger'
// console logger
const logger1 = createLogger('console')
// file logger
const logger2 = createLogger('file')

重构一下

上面的 if else 不是很优雅?如果有更多中 logger 类型添加起来很麻烦?那我们可以使用对象来映射一下,从而抛弃 if else,同时添加一个 logger 选项。

// logger/index.js
import ConsoleLogger from './console.js'
import FileLogger from './file.js'

const loggerMap = {
 console: ConsoleLogger,
 file: FileLogger
}
// 可选参数一般放在最后面
function createLogger(options, type = 'console') {
 const Logger = loggerMap[type]
 if (Logger) {
  return new Logger(options)
 }
 throw new Error(`Logger type not found: ${type}`)
}
上面这种封装的方式,其实也符合 SOLID 原则中的 开闭原则,即 对扩展开放,对修改关闭,每当我们添加一种 logger 类型时,只需要新增一个文件,然后将构造器注册进 loggerMap 中即可。而外面的使用方式都是不变的,这样就用最少的修改完成了功能的新增,是不是很棒呀~

总结

下面我们来回顾一下工厂模式的优点:

  • 动态创建对象:可以用于需要在 运行时 确定对象类型的情况。
  • 抽象:封装了对象创建的细节,用户不会接触到对象的构造器,只需要告诉工厂需要哪种对象。
  • 可用性 / 可维护性:将相似的对象用一个工厂管理,提供统一的创建接口,满足 开闭原则,使我们可以轻松添加多种类型的对象,而无需修改大量代码。

好啦~!工厂模式就介绍到这里啦~ 下次我们讲一讲装饰器模式~

参考内容

  • JavaScript Object Oriented Patterns: Factory Pattern
  • 《JavaScript 设计模式》
  • 《JavaScript 面向对象编程指南》

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
11款新鲜的jQuery插件[附所有demo下载]
Jan 24 Javascript
JavaScript中用getDate()方法返回指定日期的教程
Jun 09 Javascript
纯CSS3代码实现滑动开关效果
Aug 19 Javascript
vue.js表格分页示例
Oct 18 Javascript
JavaScript将base64图片转换成formData并通过AJAX提交的实现方法
Oct 24 Javascript
js正则表达式验证表单【完整版】
Mar 06 Javascript
纯JS实现只能输入数字的简单代码
Jun 21 Javascript
详解使用nvm管理多版本node的方法
Aug 30 Javascript
帝国cms首页列表页实现点赞功能
Oct 30 Javascript
Angular父子组件通过服务传参的示例方法
Oct 31 Javascript
jquery实现Ajax请求的几种常见方式总结
May 28 jQuery
微信小程序报错: thirdScriptError的错误问题
Jun 19 Javascript
JS 设计模式之:单例模式定义与实现方法浅析
May 06 #Javascript
基于vue3.0.1beta搭建仿京东的电商H5项目
May 06 #Javascript
JavaScript布尔运算符原理使用解析
May 06 #Javascript
ES5 模拟 ES6 的 Symbol 实现私有成员功能示例
May 06 #Javascript
Vue 的双向绑定原理与用法揭秘
May 06 #Javascript
微信小程序中使用 async/await的方法实例分析
May 06 #Javascript
JavaScript常用工具函数大全
May 06 #Javascript
You might like
php面向对象全攻略 (十五) 多态的应用
2009/09/30 PHP
PHP 用数组降低程序的时间复杂度
2009/12/04 PHP
destoon官方标签大全
2014/06/20 PHP
smarty表格换行实例
2014/12/15 PHP
通过php删除xml文档内容的方法
2015/01/23 PHP
PHP邮件群发机实现代码
2016/02/16 PHP
在IE,Firefox,Safari,Chrome,Opera浏览器上调试javascript
2008/12/02 Javascript
用jquery ajax获取网站Alexa排名的代码
2009/12/12 Javascript
通过JS动态创建一个html DOM元素并显示
2014/10/15 Javascript
Node.js学习入门
2017/01/03 Javascript
原生js实现焦点轮播图效果
2017/01/12 Javascript
angularJS利用ng-repeat遍历二维数组的实例代码
2017/06/03 Javascript
深入理解Vue父子组件生命周期执行顺序及钩子函数
2018/08/12 Javascript
vue-week-picker实现支持按周切换的日历
2019/06/26 Javascript
详解vue beforeEach 死循环问题解决方法
2020/02/25 Javascript
vue3.0中友好使用antdv示例详解
2021/01/05 Vue.js
[46:48]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第三局
2016/02/25 DOTA
[48:52]DOTA2上海特级锦标赛A组小组赛#2 Secret VS CDEC第一局
2016/02/25 DOTA
Python Web框架Pylons中使用MongoDB的例子
2013/12/03 Python
python使用sorted函数对列表进行排序的方法
2015/04/04 Python
python使用电子邮件模块smtplib的方法
2016/08/28 Python
用Python将动态GIF图片倒放播放的方法
2016/11/02 Python
Python实现重建二叉树的三种方法详解
2018/06/23 Python
python 画出使用分类器得到的决策边界
2019/08/21 Python
python中p-value的实现方式
2019/12/16 Python
踩坑:pytorch中eval模式下结果远差于train模式介绍
2020/06/23 Python
澳大利亚香水在线:Price Rite Mart
2017/12/28 全球购物
Omio葡萄牙:全欧洲低价大巴、火车和航班搜索和比价
2019/02/09 全球购物
什么是规则表达式
2012/05/03 面试题
工业设计专业个人求职信范文
2013/12/28 职场文书
清洁工岗位职责
2014/01/29 职场文书
化学系大学生自荐信范文
2014/03/01 职场文书
保护环境演讲稿
2014/05/10 职场文书
领导班子奢靡之风查摆问题及整改措施
2014/09/27 职场文书
2015年教师节演讲稿范文
2015/03/19 职场文书
Python编程根据字典列表相同键的值进行合并
2021/10/05 Python