工厂模式在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 相关文章推荐
网页前端优化之滚动延时加载图片示例
Jul 13 Javascript
jquery中的ajax方法怎样通过JSONP进行远程调用
May 04 Javascript
使用jquery+CSS实现控制打印样式
Dec 31 Javascript
JS通过ajax动态读取xml文件内容的方法
Mar 24 Javascript
jQuery分页插件jquery.pagination.js使用方法解析
Feb 09 Javascript
JavaScript实现简单的四则运算计算器完整实例
Apr 28 Javascript
Vue2几种常见开局方式详解
Sep 09 Javascript
React-Native使用Mobx实现购物车功能
Sep 14 Javascript
vue系列之requireJs中引入vue-router的方法
Jul 18 Javascript
vue自定v-model实现表单数据双向绑定问题
Sep 03 Javascript
详解在微信小程序的JS脚本中使用Promise来优化函数处理
Mar 06 Javascript
关于layui 实现点击按钮添加一行(方法渲染创建的table)
Sep 29 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中$_GET与$_POST过滤sql注入的方法
2014/11/03 PHP
php求一个网段开始与结束IP地址的方法
2015/07/09 PHP
laravel 实现上传图片到本地和前台访问示例
2019/10/21 PHP
直接生成打开窗口代码,不必下载
2008/05/14 Javascript
javascript 写类方式之九
2009/07/05 Javascript
jQuery浏览器CSS3特写兼容实例
2015/01/19 Javascript
javascript 对象数组根据对象object key的值排序
2015/03/09 Javascript
jQuery操作表单常用控件方法小结
2015/03/23 Javascript
JavaScript中switch语句的用法详解
2015/06/03 Javascript
原生js实现数字字母混合验证码的简单实例
2015/12/10 Javascript
js面向对象的写法
2016/02/19 Javascript
Javascript 创建类并动态添加属性及方法的简单实现
2016/10/20 Javascript
js Canvas实现的日历时钟案例分享
2016/12/25 Javascript
js原生Ajax的封装和原理详解
2017/03/11 Javascript
详解基于angular-cli配置代理解决跨域请求问题
2017/07/05 Javascript
jQuery实现的移动端图片缩放功能组件示例
2020/05/01 jQuery
vuecli3.x中轻松4步带你使用tinymce的步骤
2020/06/25 Javascript
Vue实现鼠标经过文字显示悬浮框效果的示例代码
2020/10/14 Javascript
[00:43]DOTA2小紫本全民票选福利PA至宝全方位展示
2014/11/25 DOTA
在Mac OS上搭建Python的开发环境
2015/12/24 Python
Python 基础之字符串string详解及实例
2017/04/01 Python
Python实现Kmeans聚类算法
2020/06/10 Python
Python简单实现两个任意字符串乘积的方法示例
2018/04/12 Python
解决python matplotlib imshow无法显示的问题
2018/05/24 Python
python matplotlib实现双Y轴的实例
2019/02/12 Python
关于Python作用域自学总结
2019/06/10 Python
Python中使用__new__实现单例模式并解析
2019/06/25 Python
python2和python3实现在图片上加汉字的方法
2019/08/22 Python
html5 offlline 缓存使用示例
2013/06/24 HTML / CSS
美国户外服装和装备购物网站:Outland USA
2020/03/22 全球购物
工商治理实习生的自我评价分享
2014/02/20 职场文书
应聘护士求职信
2014/07/21 职场文书
公司领导班子召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
2015大学迎新晚会策划书
2015/07/16 职场文书
Python语言内置数据类型
2022/02/24 Python
 分享一个Python 遇到数据库超好用的模块
2022/04/06 Python