工厂模式在JS中的实践


Posted in Javascript onJanuary 18, 2017

一.   写在前面

 工厂模式和抽象工厂在后台代码中的使用,相信你一定非常熟悉,所以关于概念的东西也用不着我多说。你可以用其做为类与类之间,层与层之间的解耦。工厂模式没有什么难点,在JS中其实思想也是一样的,所以废话不多说,直接上实践的场景和代码。

二.  场景描述

 1.最近的项目的登陆使用了Owin认证,所以token必须找好地方进行存储,鉴于token需要在请求API资源的时候放到请求头的Authorization当中,以便在进入WebAPI前进行身份验证。所以我不想在主流浏览器中的cookie中存储token,因为这样一来,每次Cookie中带一份token,Authorization中又带一份token.多传输一次不说,还让人感到很low.这么 这么low的行为,你忍心使用吗。所以我希望把token存储于localStorage当中。那么问题来了,不支持H5的浏览器怎么办?

 2.为了将来把所有前端资源置于CDN, 前端仅拥有html,css和js。页面加载到浏览器客户端后,所有动态资源走AJAX,并且所有资源均跨域。那么问题又来了,跨域很容易解决,在IE8,IE9这种默认关闭跨域功能的浏览器怎么办?

三. 公共JS结构一览

我通常会给应用定义一个全局Application.js。其中大概包括如下内容。 先上整体代码结构,供参考

工厂模式在JS中的实践

工厂模式在JS中的实践

四. 引入工厂思想解决问题

为了解决上述两个问题,所以引入工厂模式,在工厂中创建对象,工厂中根据不同浏览器类型,创建不同对象。

也就是说在解决问题一上,在浏览器支持H5的时候,存储token于localStorage。在不支持h5的浏览器中还是存于cookie.

所以产生了两个JS对象,CookieStorageUtil对象,LocalStorageUtil对象。并且他们应该实现相同的“接口”,在这里我没有使用JS代码来模仿接口,而是采用注释的形式,标注两个对象需要实现相同的接口,实现接口中的两个方法write()和get()。并规范代码,下划线开头的为私有方法,这样一来今后修改内部代码的时候,私有方法随便改,对外部暴露的方法名称不变就好,是不是有点像后台的面向接口编程呢?其实JS也是一样的。再多费一句话,如果我不使用JS的function模拟类的话,是无法达到真正的方法私有,所以如果有人调用下划线'_'开头的私有方法,在今后私有方法有变动的时候影响了功能,那就不是我的锅咯?

还是上代码靠谱:

/**
  * Storage Factory -Author 吴双 cnblogs.com/tdws
  */
 StorageUtilManager: new Object({
  createStorageUtil: function () {
   if (window.applicationCache) {
    return AppUtil.LocalStorageUtil;
   } else {
    return AppUtil.CookieStorageUtil;
   }
  }
 }),
 /**
  * implement Storage -Author 吴双
  * write()
  * get()
  */
 CookieStorageUtil: {
  write: function (key, dataObj) {
   this._clearCookie(key);
   //写入的字符串
   var dataObjStr = JSON.stringify(dataObj);
   this._setCookie(key, dataObjStr, 15);
  },
  get: function (key) {
   return this._getCookie(key);
  },
  _setCookie: function (cname, cvalue, exdays) {
   var d = new Date();
   d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
   var expires = "expires=" + d.toUTCString();
   var path = "path=/";
   document.cookie = cname + "=" + cvalue + "; " + expires + "; " + path;
  },
  _getCookie: function (cname) {
   var name = cname + "=";
   var ca = document.cookie.split(';');
   for (var i = 0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') c = c.substring(1);
    if (c.indexOf(name) != -1) return c.substring(name.length, c.length);
   }
   return null;
  },
  _clearCookie: function (key) {
   this._setCookie(key, "", -1);
  }
 },
 /**
  * implement Storage cnblogs.com/tdws
  * write()
  * get()
  */
 LocalStorageUtil: {
  write: function (key, dataObj) {
   this._writeLocalStorage(key, dataObj);
  },
  get: function (key) {
   return this._getFromLocalStorage(key);
  },
  _writeLocalStorage: function (key, dataObj) {
   var localStorage = window.localStorage;
   localStorage.removeItem(key);
   //对象转化为字符串,将objStr按正常的方式存入localStorage中
   var dataObjStr = JSON.stringify(dataObj);
   localStorage.setItem(key, dataObjStr);
  },
  _getFromLocalStorage: function (key) {
   var localStorage = window.localStorage;
   return localStorage.getItem(key);
  },
  _removeLocalStorage: function (key) {
   var localStorage = window.localStorage;
   localStorage.removeItem(key);
  }
 }

这样第二个问题也得到了解决,在不支持跨域的浏览器创建XDomainRequest对象来做请求,两个HttpUtil对象依然实现相同的接口中的方法。在这个跨域问题上,推荐使用gayhub中的一个1.8k的JS https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest

对了,为了避免使用工厂模式,使代码调用复杂,我们可以简化JS

AppUtil.currentHttpUtil = AppUtil.HttpUtilManager.createHttpUtil();

五. 写在最后

所以有了这样的方式,问题平滑的解决了,两个StorageUtil与调用方,通过工厂StorageUtilManager完成解耦。可能你看完代码后说,不就是多了一个Manager吗?这也很简单啊,是啊,就是这么简单,这就是设计模式,它仅仅是前人的经验模式,它更平滑的解决我们的实际问题。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
自己开发Dojo的建议框架
Sep 24 Javascript
Ext 表单布局实例代码
Apr 30 Javascript
Javascript 面向对象(一)(共有方法,私有方法,特权方法)
May 23 Javascript
Android中的jQuery:AQuery简介
May 06 Javascript
原生js结合html5制作简易的双色子游戏
Mar 30 Javascript
js获取滚动距离的方法
May 30 Javascript
JS判断日期格式是否合法的简单实例
Jul 11 Javascript
原生JS实现左右箭头选择日期实例代码
Mar 14 Javascript
关于javascript获取内联样式与嵌入式样式的实例
Jun 01 Javascript
10分钟彻底搞懂Http的强制缓存和协商缓存(小结)
Aug 30 Javascript
JS实现滑动插件
Jan 15 Javascript
javascript中innerHTML 获取或替换html内容的实现代码
Mar 17 Javascript
基于jQuery制作小图标上下滑动特效
Jan 18 #Javascript
JQuery Dialog对话框 不能通过Esc关闭的原因分析及解决办法
Jan 18 #Javascript
动态加载css方法实现和深入解析
Jan 18 #Javascript
用jQuery实现可输入多选下拉组合框实例代码
Jan 18 #Javascript
JS实现旋转木马式图片轮播效果
Jan 18 #Javascript
微信小程序实现图片预加载组件
Jan 18 #Javascript
JavaScript原生节点操作小结
Jan 17 #Javascript
You might like
php程序的国际化实现方法(利用gettext)
2011/08/14 PHP
php中使用array_filter()函数过滤空数组的实现代码
2014/08/19 PHP
thinkphp实现like模糊查询实例
2014/10/29 PHP
PHP基于DateTime类解决Unix时间戳与日期互转问题【针对1970年前及2038年后时间戳】
2018/06/13 PHP
PHP FileSystem 文件系统常用api整理总结
2019/07/12 PHP
设定php简写功能的方法
2019/11/28 PHP
php下的原生ajax请求用法实例分析
2020/02/28 PHP
详解阿里云视频直播PHP-SDK接入教程
2020/07/09 PHP
一样的table?不一样的table(可编辑状态table)
2012/09/19 Javascript
jquery.Ajax()方法调用Asp.Net后台的方法解析
2014/02/13 Javascript
有关jquery与DOM节点操作方法和属性记录
2016/04/15 Javascript
基于Bootstrap使用jQuery实现简单可编辑表格
2016/05/04 Javascript
javascript jquery对form元素的常见操作详解
2016/06/12 Javascript
一个仿微博登陆邮箱提示框js开发案例
2016/07/28 Javascript
详解Javascript数据类型的转换规则
2016/12/12 Javascript
js实现canvas图片与img图片的相互转换的示例
2017/08/31 Javascript
jQuery实现鼠标响应式淘宝动画效果示例
2018/02/13 jQuery
如何获取TypeScript的声明文件.d.ts
2018/05/01 Javascript
js blob类型url的视频下载问题的解决
2019/11/29 Javascript
vue flex 布局实现div均分自动换行的示例代码
2020/08/05 Javascript
[02:36]DOTA2上海特锦赛 回忆电竞生涯的重要瞬间
2016/03/25 DOTA
[01:04:09]DOTA2-DPC中国联赛 正赛 iG vs VG BO3 第二场 2月2日
2021/03/11 DOTA
python中map、any、all函数用法分析
2015/04/21 Python
简单介绍Python中的round()方法
2015/05/15 Python
Python中的localtime()方法使用详解
2015/05/22 Python
利用Anaconda简单安装scrapy框架的方法
2018/06/13 Python
pytorch 加载(.pth)格式的模型实例
2019/08/20 Python
Tensorflow之梯度裁剪的实现示例
2020/03/08 Python
python如何获得list或numpy数组中最大元素对应的索引
2020/11/16 Python
西班牙多品牌鞋店连锁店:Krack
2018/11/30 全球购物
意大利在线眼镜精品店:Ottica Lipari
2019/11/11 全球购物
幼师自荐信
2013/10/26 职场文书
事业单位分类改革实施方案
2014/03/21 职场文书
通信工程求职信
2014/07/16 职场文书
党员干部群众路线个人整改措施
2014/09/18 职场文书
《飘》英文读后感五篇
2019/10/11 职场文书