为了账号安全,请及时绑定邮箱和手机立即绑定

单例模式

设计模式

通俗讲,设计模式只是大量有经验的开发者在面对相同问题时,无数次使用过的解决方案。
可能很多人认为设计模式并没有多大用途,毕竟用普通的方法就能解决的问题,何必把代码逻辑搞得如此复杂,但从代码的可复用性和可维护性来看,好的设计的确可以节省大量的开发成本。优秀的 JavaScript 框架都运用了大量设计模式。

单例模式

单例模式的核心是确保只有一个实例对象,并提供全局访问。

使用场景

试想一下这样的场景,页面有一个登录窗,这个登录窗是唯一的,那么这个登录窗就非常适合用单例模式来创建。
我们可能会选择将这个登录窗定义在全局环境中:

例子:

<button id="login">登录</button>

<script>
    var loginBox = (function() {
        var div = document.createElement("div");
        div.innerHTML = "登录窗";
        div.style.backgroundColor = "bisque";
        div.style.display = "none";
        document.body.appendChild(div);
        return div;
    })();

    document.getElementById("login").onclick = function() {
        loginBox.style.display = "block";
    };
</script>

例子中,我们将登录窗缓存在全局环境中并隐藏起来,当用户点击时,才开始展示。这种单例模式称为饿汉式单例,即实例在页面加载完成时就被创建。
登录窗定义在全局存在很多问题,容易造成命名空间污染,所以有必要减少全局变量的使用。最为理想的方式是将实例封装在闭包中,只暴漏外部访问的接口。
另外,我们打开页面,可能根本不会点击登录按钮,那么加载的数据只是白白浪费内存而已,因此,与饿汉式单例相反的、实际工作中使用更多的是懒汉式单例,即实例在第一次引用时才被创建,然后将结果缓存在闭包中。

例子:

<button id="login">登录</button>

<script>
    var createLoginBox = (function() {
        var div;
        return function() {
            if (!div) {
                div = document.createElement("div");
                div.innerHTML = "登录窗";
                div.style.backgroundColor = "bisque";
                document.body.appendChild(div);
            }
            return div;
        }
    })();

    document.getElementById("login").onclick = function() {
        createLoginBox();
    };
</script>

通用懒汉式单例

页面中,往往不止一种弹出窗,如果下次我们需要创建确认框,就去复制现有的单例方法,这明显不是明智的做法。
理想的做法是将单例方法中变化的部分抽离出来,然后再以回调函数的形式传回给单例。本例中,创建弹窗的代码是变化的,而管理单例的代码是不变的,因此我们将创建弹窗的代码单独放置在一个方法里,这样一来,原来的单例方法中,只剩下可以通用的代码。

例子:

<button id="login">登录</button>
<button id="confirm">确认</button>

<script>
    //管理单例的逻辑始终是一样的
    var createSing = function() {
        var result;
        return function(fn) {
            if (!result) {
                result = fn();
            }
            return result;
        }
    };

    //创建登录窗的方法
    var createLoginBox = function() {
        var div = document.createElement("div");
        div.innerHTML = "登录窗";
        div.style.backgroundColor = "#ffe4c4";
        document.body.appendChild(div);
        return div;
    };

    //创建确认窗的方法
    var createConfirmBox = function() {
        var div = document.createElement("div");
        div.innerHTML = "确认窗";
        div.style.backgroundColor = "#ff5722";
        document.body.appendChild(div);
        return div;
    };

    //为登录窗创建一个实例
    var login = createSing();
    document.getElementById("login").onclick = function() {
        login(createLoginBox);
    };

    //为确认窗创建一个实例
    var confirm = createSing();
    document.getElementById("confirm").onclick = function() {
        confirm(createConfirmBox);
    };
</script>

如有错误,欢迎指正,本人不胜感激。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消