设计模式(一):单例模式

来源:互联网 发布:shopnc b2b2c 源码 编辑:程序博客网 时间:2024/05/21 09:19

单例模式

单例模式保证一个类仅有一个实例,并且这一实例可被全局访问。
JS中并没有类的概念,最简单的单例模式就是声明全局变量,而为了减少全局变量的数量避免命名污染,我们常常使用以下两种方式实现单例。

1. 命名空间

使用对象字面量划分命名空间减少了全局变量的数量。

var Lean = {    event: {        addEvent: function(){ }    },    dom: {        ...    }}

2. 闭包

使用闭包暴露特定接口供外部访问。

var Lean = function(){    //私有属性    var name = 'zz';    return{        //公有方法        getName:function(){            return 'name:' + name;        }    }}

惰性单例

惰性单例是仅在需要的时候才创建对象实例。不像前面的单例模式,页面一旦加载,单例对象就会被创建。

1. 弹框/弹出层

当我们需要一个点击弹框效果时,一般思路是先创建好这个弹框,再通过按钮注册点击事件来实现弹框的显示与隐藏。但这种方式有一个缺陷,如果用户没有点击这一按钮,那么为弹框而创建的DOM节点都是白白浪费的。这时候惰性单例模式就派上用场了。我们使用一个变量来判断当前是否创建过弹框。
var createPopup = (function(){    var pop;    return function(){        if(!pop){            pop = document.createElement('div');            pop.innerHTML = 'popup';            pop.style.display = 'none';            document.body.appendChild(pop);        }        return pop;    }})();btn.onclick = function(){    var oDiv = createPopup();    oDiv.style.display = 'block';};

2. 封装

当我们需要创建页面上唯一的iframe或者利用JSONP创建script标签来跨域请求数据时等许多场景都需要用到惰性单例模式,我们可以将其中的固定逻辑抽离出来封装成一个函数以复用。

var createSingle = function(fn){    var res;    return function(){        return res || (res = fn.apply(this, arguments));    }};
利用闭包特性,函数中的res变量被留在内存中不会被销毁。因此可得知单例对象当前是否已经被创建。

3. 实践

现在我们来利用单例模式做一个上述弹框效果。

HTML

<body>    <button id="alert">Alert</button>    <button id="confirm">Confirm</button>    <!--<div class="wrap">        <div class="box">            <h3 class="title">提示</h3>            <div class="close">✖</div>            <p class="msg"></p>            <a class="ok" href="javascript:;">确定</a>        </div>    </div>--></body>

JavaScript

//类名选择器var $ = function(sClass) {    return document.getElementsByClassName(sClass)[0];}//参数:弹框类型 标题 内容 回调函数var Popup = function(sType, sTitle, sMsg, fn) {    var oWrap = document.createElement('div');    document.body.appendChild(oWrap);    oWrap.className = 'popup-wrap';    oWrap.style.display = 'none';    //根据参数确定弹框类型    if (sType == 'alert') {        oWrap.innerHTML = '...';    } else if (sType == 'confirm') {        oWrap.innerHTML = '...';    }    return oWrap;}//惰性单例逻辑var createSingle = function(fn){    var res;    return function(){        return res || (res = fn.apply(this, arguments));    }};var createSinglePop = createSingle(Popup);var oAlert = document.getElementById('alert');var oConf = document.getElementById('confirm');//注册click事件oAlert.onclick = function(){    var o = createSinglePop('alert', 'Alert Title', 'Hello World');    o.style.display = 'block';}oConf.onclick = function(){    var c = createSinglePop('confirm', 'Confirm Title', 'This is confirm content', () => alert('callback'));    c.style.display = 'block';}

JS Bin 查看效果

原创粉丝点击