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 相关文章推荐
JQuery 学习笔记 选择器之四
Jul 23 Javascript
Mootools 1.2教程 类(一)
Sep 15 Javascript
JSON辅助格式化处理方法
Mar 26 Javascript
jquery对元素拖动排序示例
Jan 16 Javascript
非常酷炫的Bootstrap图片轮播动画
May 27 Javascript
JS正则子匹配实例分析
Dec 22 Javascript
Ionic+AngularJS实现登录和注册带验证功能
Feb 09 Javascript
Spring Boot+AngularJS+BootStrap实现进度条示例代码
Mar 02 Javascript
详解vue2.0 使用动态组件实现 Tab 标签页切换效果(vue-cli)
Aug 30 Javascript
Javascript中绑定click事件的四种方式介绍
Oct 26 Javascript
微信小程序实现吸顶效果
Jan 08 Javascript
Html5生成验证码的示例代码
May 10 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
基于Laravel实现的用户动态模块开发
2017/09/21 PHP
彻底搞懂PHP 变量结构体
2017/10/11 PHP
javascript制作的网页侧边弹出框思路及实现代码
2014/05/21 Javascript
搭建pomelo 开发环境
2014/06/24 Javascript
AngularJS中如何使用echart插件示例详解
2016/10/26 Javascript
Bootstrap源码解读下拉菜单(4)
2016/12/23 Javascript
详解vue嵌套路由-query传递参数
2017/05/23 Javascript
微信小程序日期时间选择器使用方法
2018/02/01 Javascript
vue嵌套路由与404重定向实现方法分析
2018/05/04 Javascript
JS实现选项卡效果的代码实例
2019/05/20 Javascript
JS函数动态传递参数的方法分析【基于arguments对象】
2019/06/05 Javascript
vue+iview使用树形控件的具体使用
2020/11/02 Javascript
Python 读写文件和file对象的方法(推荐)
2016/09/12 Python
python+opencv实现的简单人脸识别代码示例
2017/11/14 Python
TF-IDF与余弦相似性的应用(二) 找出相似文章
2017/12/21 Python
python实现微信发送邮件关闭电脑功能
2018/02/22 Python
python 计算数据偏差和峰度的方法
2019/06/29 Python
python修改字典键(key)的方法
2019/08/05 Python
Python换行与不换行的输出实例
2020/02/19 Python
python数据预处理 :数据共线性处理详解
2020/02/24 Python
对python中return与yield的区别详解
2020/03/12 Python
django 模版关闭转义方式
2020/05/14 Python
python调用摄像头的示例代码
2020/09/28 Python
Html5让容器充满屏幕高度或自适应剩余高度的布局实现
2020/05/14 HTML / CSS
会计专业自我鉴定范文
2013/10/06 职场文书
投标保密承诺书
2014/05/19 职场文书
春节超市活动方案
2014/08/14 职场文书
群众路线教育实践活动个人对照检查材料思想汇报(社区班子)
2014/10/06 职场文书
党的群众路线学习笔记
2014/11/06 职场文书
2014年内勤工作总结
2014/11/24 职场文书
教师个人考察材料
2014/12/16 职场文书
2015年南京大屠杀纪念日活动总结
2015/03/24 职场文书
请客吃饭开场白
2015/06/01 职场文书
读《解忧杂货店》有感:请相信一切都是最好的安排
2019/11/07 职场文书
解决mysql的int型主键自增问题
2021/07/15 MySQL
python开发的自动化运维工具ansible详解
2021/08/07 Python