单体是一个用来划分命名空间并将一些相关的属性与方法组织在一起的对象,如果她可以被实例化的话,那她只能被实例化一次(她只能嫁一次,不能二婚)。

单体模式是javascript里面最基本但也是最有用的模式之一。

特点:1. 可以用来划分命名空间,从而清除全局变量所带来的危险或影响。

   2. 利用分支技术来来封装浏览器之间的差异。

     3. 可以把代码组织的更为一体,便于阅读和维护。

单体模式的基本写法:

/* 最基本的单体模式 */
var her = {
   name: 'Anna',
   sex: 'women',
   say: function(){
        // 一些处理逻辑......
   },
   doing: function(){
        // 另一些处理函数......
    }
}

 1. 划分命名空间:

var box = {
    width: 0,
    height: 0,
    getArea: function(){
         return this.width * this.width; // js中对象成的访问必须是显示的,即this是不能省略的
    },
    init: function(w, h){
         // width = w;
         // height = h;这种方式相当于定义了两个全局变量,(没加var声明的变量为全局变量)
         // 并不是对对象width和height的赋值
         // 下面是正确的
         this.width = w;
         this.height = h;
    }
} //box划分了一个命名空间,命名空间里的变量只在空间里有效

上面的单体中的所有的成员以及方法都是公有的(public),也就是在单体的外部可以对她们进行任意的改动(但不能访问其中的局部变量),那为什么说单体提供了一个命名空间呢?

别急,我们接着往下看:

var box = {
        width:0,
        height:0,//单体的变量
        getArea:function(){
            return width * height;// width,height其实并不是单体的变量,而是在init中定义的全局变量
        }
        init:function(w,h){
            width = w;
            height = h;
        }
}// init中width,height其实并不是单体的变量
window.onload = function(){
    var init = box.getArea();
    alert(init);
}

由于没有对init中的width,height进行初始化,所以会报错,这样改一下:

var box = {
        width:0,
        height:0,
        getArea:function(){
            return width * height;
        },
        init:function(w,h){
            width = w;
            height = h;
        }
    }
window.onload = function(){
        width = 0;
        height = 0;
        //or box.init(0,0);
        var init = box.getArea();
    alert(init);
}

发现可以了,由于init和 getArea所用的width和height并不是归单体所有的变量,而是一个全局变量,所以我们可以在单体外面进行随意调用而不受影响、

var box = {
        width: 0,
        height: 0,
        getArea: function(){
            return width * height;//js中对象成的访问必须是显示的,即this是不能省略的
        },
        init:function(w,h){
            width = w;
            height = h;
        }
    }//这里的width,height其实并不是单体的对象
window.onload = function(){
        width = 0;
        height = 0;
        var width = box.getArea();
        alert(width);
}

这样写又会报错了,可见我们以上的方式对于全局变量并没有建立起一个命名空间,全局变量为我们带来了危险。所以最上面的写法是对的,我们来验证一下:

var box = {
        width: 2,
        height: 2,
        getArea: function(){
            return this.width * this.height;/ /js中对象成的访问必须是显示的,即this是不能省略的
        },
        init:function(w,h){
            this.width = w;
            this.height = h;
        }
    }
window.onload = function(){
        width = 0; // 不会影响单体中的局部变量也就是命名空间
        height = 0; // 不会影响单体中的局部变量也就是命名空间
        var width = box.getArea();
        alert(width);
}

可见在window.onload中的width 和height已经没有干扰了,因为单体为单体中的width和height建立了一个命名空间。

2. 成员的属性:

虽然在javascript中没有这么严格的面向对象(oop),但是我们可以借助闭包来进行一个模仿,毕竟有的变量设为public是很不好的。

var her = (function(){
    var name  = 'Anna';
    var sex = 'women';
    return {
         getArea: function(){
             return name + 'is a'  + sex;
         },
         init:function(b){
               name = b;
         }
    }
})();

window.onload = function(){
    her.name = 'Jock'; // 无法访问
    alert(ger.getArea());
    her.init('Lous');
    alert(her.getArea());
}

私有变量、方法是只读的,公有变量、方法是可读可写的。

访问:
对于私有成员,直接访问即可,前面不用加任何修饰,
对于公有的访问在单体作用域内前面要加上“this.”,在单体作用域外前面要加上“her.”(单体名字.)

3.利用分支技术来来封装浏览器之间的差异

注意的地方:

  a. 一定要用闭包,实现即时绑定

  b. 每个分支之间用分号隔开

  c. 最后返回的是分支的名字

  d. 调用的时候用单体名+分支的方法名;

// 利用单体的分支技术来定义XHR(XMLHttpRequest)对象,必须要用闭包才可以实现
var XHR = (function(){
    //The three branches
    var standard = {
        cXHR:function(){
                return new XMLHttpRequest();
            }
    };
    var activeXNew = {
        cXHR:function(){
                return new ActiveXObject('Msxml2.XMLHttp');
            }
    };
    var activeXOld = {
        cXHR:function(){
                return new ActiveXObject('Microsoft.XMLHttp');
            }
    };
    //To assign(分配) the branch, try each method;return whatever doesn't fail
    var testObject;
    try{
        testObject = standard.cXHR();
        return standard;// return this branch if no error was thrown
    }catch(e){
        try{
            testObject = activeXNew.cXHR();
            return activeXNew;
        }catch(e){
            try{
                testObject = activeXOld.cXHR();
                return activeXOld;
            }catch(e){
                throw new Error('Create the XMLHttpRequestObject failed!');
            }
        }
    }
})();
window.onload = function(){
    alert(XHR.cXHR());
}

共同进步吧!!!话说又星期五了

javascript --- 设计模式之单体模式(一)的更多相关文章

  1. javascript设计模式之单体模式

    一入前端深似海,刚入前端,以为前端只是div+css布局外加jquery操作DOM树辣么简单.伴随着对前端学习的深入,发现前端也是博大精深,而且懂得越多,才发现自己越无知,所以一定不能停下脚步的学习. ...

  2. javascript设计模式(单体模式)

    主要内容: js中最基本.应用最广的模式就是单体模式,实现原理是将代码组织为一个逻辑单元,这个逻辑单元中的代码可以通过单一的变更进行访问,确保对象只存在一份实例. 单体模式的特点: 在网页中使用全局变 ...

  3. Javascript设计模式(2)-单体模式

    单体模式 1. js最简单的单体模式 对象字面量:把一批有一定关联的方法和属性组织在一起 // 对象字面量 var Singleton = { attr1: true, attr2: 10, meth ...

  4. javascript --- 设计模式之单体模式(二)

    在JavaScript里,实现单例的方式有很多种,其中最简单的一个方式是使用对象字面量的方法,其字面量里可以包含大量的属性和方法: var her = { property1: 'someing', ...

  5. JS设计模式——5.单体模式

    JS设计模式——5.单体模式 http://www.cnblogs.com/JChen666/p/3610585.html   单体模式的优势 用了这么久的单体模式,竟全然不知!用它具体有哪些好处呢? ...

  6. JavaScript设计模式之----组合模式

    javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...

  7. JS设计模式之单体模式(Singleton)

    单体模式作为一种软件开发模式在众多面向对象语言中得到了广泛的使用,在javascript中,单体模式也是使用非常广泛的,但是由于javascript语言拥有其独特的面向对象方式,导致其和一些传统面向对 ...

  8. 从ES6重新认识JavaScript设计模式(三): 建造者模式

    1 什么是建造者模式? 建造者模式(Builder)是将一个复杂对象的构建层与其表示层相互分离,同样的构建过程可采用不同的表示. 建造者模式的特点是分步构建一个复杂的对象,可以用不同组合或顺序建造出不 ...

  9. JavaScript 设计模式之----单体(单例)模式

    设计模式之--单体(单例)模式 1.介绍 从本章开始,我们会逐步介绍在JavaScript里使用的各种设计模式实现,在这里我不会过多地介绍模式本身的理论,而只会关注实现.OK,正式开始. 在传统开发工 ...

随机推荐

  1. ping: sendto: Network is unreachable

    在我的板子上ping路由上的IP的时候可以ping通,但是ping外网的IP的时候提示"ping: sendto: Network is unreachable" 后来使用rout ...

  2. [原]Ubuntu 14.04编译Android Kernel

    如何编译android kernel参考官方文档:https://source.android.com/source/building-kernels.html   在Ubuntu 14.04上编译a ...

  3. 使用的 SQL Server 版本不支持数据类型“datetime2”的错误解决方法

    THE VERSION OF SQL IN USE DOES NOT SUPPORT DATATYPE ‘DATETIME2′ 主要错误原因,在使用ado.net entity的时候,entity使用 ...

  4. EF Attach时已存在的处理方式

    如果我们在先前的步骤中读取过数据,如 var list = db.Model.ToList(); 之后再,附加 var o = new Model { Id = 1 }; db.Model.Attac ...

  5. php分享三十三:用php中的register_shutdown_function和fastcgi_finish_request

    已前言 在php中又两个方法都是在请求快结束的时候执行.方法名分别是 register_shutdown_function和fastcgi_finish_request.虽然执行的时机差不多,但是功能 ...

  6. Android manifest之manifest标签详细介绍

    AndroidManifest详细介绍 本文主要对AndroidManifest.xml文件中各个标签进行说明.索引如下: 概要PART--01 manifest标签PART--02 安全机制和per ...

  7. 移除了css框架,世界干净了

    在之前的webapp项目里,我使用了bootstrap作为三方的css库,只调取了其中一部分源码的less使用,大部分代码仍然是自己写的. 自己的代码也是参照bootstrap的目录结构和它的一些规范 ...

  8. 网游中的网络编程3:在UDP上建立虚拟连接

    目录 网游中的网络编程系列1:UDP vs. TCP 网游中的网络编程2:发送和接收数据包 网游中的网络编程3:在UDP上建立虚拟连接 TODO 二.在UDP上建立虚拟连接 介绍 UDP是无连接的,一 ...

  9. 【Spark】----Spark on Yarn

    最近从Hadoop 1.x 转到Hadoop 2.x 同时将一些java 程序转为Scala的程序将平台上的代码减少了很多,在实施的过程中,开到一些Spark相关的YARN的部署上都是基于之前的Had ...

  10. 12 19 spring3 项目总结

    项目截图: 林集团 https://home.cnblogs.com/u/linjituan/ 团队guihub: https:///github.com/MoiGi 李鹏飞 https://www. ...