javascript常用的设计模式


Posted in Javascript onFebruary 09, 2017

js最好是一种面向对象的语言。它的出现时比较迟的。但是它是目前最火的脚本语言。而且,随着近期的微信商城等页面的兴起,相信程序员和互联网的从业者都知道了js正在势头上了。

那么,如果你想要在前端这条路上走得更远,设计模式就必须要懂。下面介绍几种常见的设计模式。

一、单例模式

单例模式也称作为单子模式,更多的也叫做单体模式。为软件设计中较为简单但是最为常用的一种设计模式。 在JavaScript里,实现单例的方式有很多种,其中最简单的一个方式是使用对象字面量的方法,其字面量里可以包含大量的属性和方法:

var mySingleton = {
property1: "something",
property2: "something else",
method1: function () {
  console.log('hello world');
}};

如果以后要扩展该对象,你可以添加自己的私有成员和方法,然后使用闭包在其内部封装这些变量和函数声明。只暴露你想暴露的public成员和方法,样例代码如下:

var mySingleton = function () {
  /* 这里声明私有变量和方法 */
  var privateVariable = 'something private';
  function showPrivate() {
    console.log(privateVariable);
  }
  /* 公有变量和方法(可以访问私有变量和方法) */
  return {
    publicMethod: function () {
      showPrivate();
    },
    publicVar: 'the public can see this!'
  };
};
var single = mySingleton();
single.publicMethod(); // 输出 'something private'
console.log(single.publicVar); // 输出 'the public can see this!'

上面的代码很不错了,但如果我们想做到只有在使用的时候才初始化,那该如何做呢?为了节约资源的目的,我们可以另外一个构造函数里来初始化这些代码,如下:

var Singleton = (function () {
  var instantiated;
  function init() {
    /*这里定义单例代码*/
    return {
      publicMethod: function () {
        console.log('hello world');
      },
      publicProperty: 'test'
    };
  }
  return {
    getInstance: function () {
      if (!instantiated) {
        instantiated = init();
      }
      return instantiated;
    }
  };
})();
/*调用公有的方法来获取实例:*/
Singleton.getInstance().publicMethod();

二、工厂模式

工厂模式是由一个方法来决定到底要创建哪个类的实例, 而这些实例经常都拥有相同的接口. 这种模式主要用在所实例化的类型在编译期并不能确定, 而是在执行期决定的情况。 说的通俗点,就像公司茶水间的饮料机,要咖啡还是牛奶取决于你按哪个按钮。

实例:

function A( name ){
       this.name = name;
    }
    function ObjectFactory(){
       var obj = {},
           Constructor = Array.prototype.shift.call( arguments );
obj.__proto__ = typeof Constructor .prototype === 'number' ? Object.prototype
: Constructor .prototype;
       var ret = Constructor.apply( obj, arguments );
       return typeof ret === 'object' ? ret : obj;
    }
    var a = ObjectFactory( A, 'svenzeng' );
    alert ( a.name ); //svenzeng

这段代码来自es5的new和构造器的相关说明, 可以看到,所谓的new, 本身只是一个对象的复制和改写过程, 而具体会生成什么是由调用ObjectFactory时传进去的参数所决定的。

三、 适配模式

简单的说,适配模式主要是为了解决一些接口不兼容产生的解决方法。借助于适配器我们可以在不修改这些不兼容接口的情况下给使用者提供统一的包装过的适配接口。表面上又感觉和之前的门面模式比较像,均是对其他对象或者接口进行包装再呈现,而适配器模式偏向的是解决兼容性问题,门面模式则偏向方便性为原则。

比如一个简单的学生查询学科成绩的方法:

function selectScore( name, id, course_id ){
  // arguments 姓名 学号 课程id
  ...
}

当我需要一个班级某门学科的整体成绩列表,而我手上只有每个学生如下的数据

[
  { name: 'lily', studentID: '0911' },
  { name: 'suny', studentID: '0912' },
  ...
]

我需要查询 英语 其课程ID为 101,那么对于该任务,写一个适配器方式是很恰当不过的

function selectEnglishScore( stutentObj ){
  selectScore( stutentObj.name, stutentObj.studentID , 101);
}

这是一个最简单的关于适配器来处理参数方面兼容的形式。 其实简单的来说,适配器模式意义上很简单 - 适配,解决兼容问题。

例子二,比如你觉得jquery里边的$选择器需要改成$id才能和你的项目搭配,那么这时候写一个方法,将$转换成$id就很轻松了。如下:

$id = function( id ){
 return jQuery( '#' + id )[0];
}

四、外观模式

外观模式(门面模式),是一种相对简单而又无处不在的模式。外观模式提供一个高层接口,这个接口使得客户端或子系统更加方便调用。 用一段再简单不过的代码来表示:

var getName = function(){
 return ''svenzeng"
}
var getSex = function(){
  return 'man'
}

如果你需要分别调用getName和getSex函数. 那可以用一个更高层的接口getUserInfo来调用.:

var getUserInfo = function(){
 var info = a() + b();
 return info;
}

也许你会问为什么一开始不把getName和getSex的代码写到一起, 比如这样:

var getNameAndSex = function(){
 return 'svenzeng" + "man";
}

答案是显而易见的,饭堂的炒菜师傅不会因为你预定了一份烧鸭和一份白菜就把这两样菜炒在一个锅里。他更愿意给你提供一个烧鸭饭套餐。同样在程序设计中,我们需要保证函数或者对象尽可能的处在一个合理粒度,毕竟不是每个人喜欢吃烧鸭的同时又刚好喜欢吃白菜。 外观模式还有一个好处是可以对用户隐藏真正的实现细节,用户只关心最高层的接口。比如在烧鸭饭套餐的故事中,你并不关心师傅是先做烧鸭还是先炒白菜,你也不关心那只鸭子是在哪里成长的。

最后写个我们都用过的外观模式例子:

var stopEvent = function( e ){  //同时阻止事件默认行为和冒泡
 e.stopPropagation();
 e.preventDefault();
}

好了,今天的额设计模式就先到这里。如果大家想要了解更多的设计模式可以去汤姆大叔的博客欣赏哦。还有,这里的很多的设计模式其实都是将解决问题的方法细化了的说法,如果去看一下prototype或者jquery都会知道,其实里边的代码很多都用到了设计模式的。

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

Javascript 相关文章推荐
JS 实现双色表格实现代码
Nov 24 Javascript
JavaScript改变HTML元素的样式改变CSS及元素属性
Nov 12 Javascript
js 获取、清空input type="file"的值(示例代码)
Dec 24 Javascript
javascript实现按回车键切换焦点
Feb 09 Javascript
原生js配合cookie制作保存路径的拖拽
Dec 29 Javascript
js仿3366小游戏选字游戏
Apr 14 Javascript
Vue.js实战之使用Vuex + axios发送请求详解
Apr 04 Javascript
vue缓存的keepalive页面刷新数据的方法
Apr 23 Javascript
JS实现简单日历特效
Jan 03 Javascript
google广告之另类js调用实现代码
Aug 22 Javascript
three.js如何实现3D动态文字效果
Mar 03 Javascript
小程序实现侧滑删除功能
Jun 25 Javascript
简单实现js选项卡切换效果
Feb 09 #Javascript
原生JS轮播图插件
Feb 09 #Javascript
jQuery页面弹出框实现文件上传
Feb 09 #Javascript
如何在Angular2中使用jQuery及其插件的方法
Feb 09 #Javascript
详解angular2采用自定义指令(Directive)方式加载jquery插件
Feb 09 #Javascript
vue-router跳转页面的方法
Feb 09 #Javascript
基于JavaScript实现复选框的全选和取消全选
Feb 09 #Javascript
You might like
PHP foreach循环使用详解与实例代码
2010/05/08 PHP
php 字符串压缩方法比较示例
2014/01/23 PHP
mac下Apache + MySql + PHP搭建网站开发环境
2014/06/02 PHP
ThinkPHP文件上传实例教程
2014/08/22 PHP
php使用ereg验证文件上传的方法
2014/12/16 PHP
利用switch语句进行多选一判断的实例代码
2016/11/14 PHP
PHP大文件分割上传 PHP分片上传
2017/08/28 PHP
jQuery打印指定区域Html页面并自动分页
2014/07/04 Javascript
JS动态修改图片的URL(src)的方法
2015/04/01 Javascript
浅谈jquery事件处理
2015/04/24 Javascript
JSON字符串转JSON对象
2015/07/31 Javascript
浅析Node.js 中 Stream API 的使用
2015/10/23 Javascript
javascript实现列表切换效果
2016/05/02 Javascript
javascript中使用未定义变量或值的情况分析
2016/07/19 Javascript
jQuery实用密码强度检测
2017/03/02 Javascript
js判断节假日实例代码
2017/12/27 Javascript
jQuery第一次运行页面默认触发点击事件的实例
2018/01/10 jQuery
基于node+websocket+html实现腾讯课堂聊天室聊天功能
2020/03/04 Javascript
JavaScript, select标签元素左右移动功能实现
2020/05/14 Javascript
如何在Express4.x中愉快地使用async的方法
2020/11/18 Javascript
浅谈Python实现2种文件复制的方法
2018/01/19 Python
python字典快速保存于读取的方法
2018/03/23 Python
Python字符串通过'+'和join函数拼接新字符串的性能测试比较
2019/03/05 Python
Python基于Opencv来快速实现人脸识别过程详解(完整版)
2019/07/11 Python
Python_查看sqlite3表结构,查询语句的示例代码
2019/07/17 Python
大女孩胸罩:Big Girls Bras
2016/12/15 全球购物
歌唱比赛获奖感言
2014/01/21 职场文书
大型车展策划方案
2014/02/01 职场文书
安踏广告词改编版
2014/03/21 职场文书
护士实习求职信
2014/06/22 职场文书
物价局领导班子四风问题整改措施
2014/10/26 职场文书
2015年宣传部部长竞选演讲稿
2014/11/28 职场文书
初中重阳节活动总结
2015/05/05 职场文书
python 实现图与图之间的间距调整subplots_adjust
2021/05/21 Python
MySQL去除密码登录告警的方法
2022/04/20 MySQL
MySQL transaction事务安全示例讲解
2022/06/21 MySQL