javascript常用的设计模式
发布在js类栏目2016年11月16日view:1723BrettBat前端工程
在文章任何区域双击击即可给文章添加【评注】!浮到评注点上可以查看详情。
 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都会知道,其实里边的代码很多都用到了设计模式的。

评论
发表评论
1年前
赞了此文章!
WRITTEN BY
往返的扁舟
一个符号不能代表什么;一堆符号能代表好多。
TA的新浪微博
PUBLISHED IN
js类栏目

js相关内容

我的收藏