JavaScript设计模式之单例模式

Posted 紅葉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript设计模式之单例模式相关的知识,希望对你有一定的参考价值。

单例模式又被称为单体模式,是只允许实例化一次的对象类。实现的方法一般是先判断实例中是否存在,如果存在则直接返回,不存在就创建了再返回,这样就确保了一个类只有一个实例对象。在javascript中,单例模式作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问改对象。

单例的常见作用:

  • 模块间通信
  • 系统中某个类的对象只能存在一个
  • 保护自己的属性和方法

应用

系统中某个类的对象只能存在一个

  例如,我们要实现点击按钮,弹出一个模态框

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        div{
            width:200px;
            height:200px;
            border:1px solid #09f;
            position: absolute;
        }
    </style>
</head>
<body>
    <input type="button" value="弹窗">
    <script>
        var oBtn = document.querySelector("input"),
        offset = 20, index = 1;
        function Module(pos){
            this.offset = pos || 20;
        };
        Module.prototype.create = function(){
            var oDiv = document.createElement("div");
            oDiv.style.left = (++index) * offset + \'px\';
            oDiv.style.top = (++index) * offset + \'px\';
            oDiv.innerHTML = \'普通弹窗\';
            return oDiv;
        };
        oBtn.onclick = function(){
            var oDiv = new Module();
            document.body.appendChild(oDiv.create());
        };
    </script>
</body>
</html>

我们希望的是,不管点击按钮多少次,都只出现一个模态框,但结果却是下面这样的:

 

 这个时候就需要用单例模式进行改造:

 <!DOCTYPE html>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     <title>Document</title>
     <style>
         div{
             width:200px;
             height:200px;
             border:1px solid #09f;
             position: absolute;
         }
     </style>
 </head>
 <body>
     <input type="button" value="弹窗1">
     <input type="button" value="弹窗2">
     <script>
         var oBtn = document.querySelectorAll("input"),
         offset = 20, index = 1;
         function Module(pos){
             this.offset = pos || 20;
         };
         Module.prototype.create = function(){
             var oDiv = document.createElement("div");
             oDiv.style.left = (++index) * offset + \'px\';
             oDiv.style.top = (++index) * offset + \'px\';
             oDiv.innerHTML = \'单例模式弹窗\';
             return oDiv;
         };
         Module.one = (function(){
             var ins = null, isExist = false;
             return function(pos){
                 if(!ins) ins = new Module(pos);
                 if(!isExist){
                     document.body.appendChild(ins.create());
                     isExist = true;
                 }
             }
         })();
         oBtn[0].onclick = function(){
             Module.one(10);
         };
         oBtn[1].onclick = function(){
             Module.one(10);
         };
     </script>
 </body>
 </html>

在Module.one中通过变量isExist的两种状态和闭包特性控制元素只能被添加一次,就可以实现只能弹出一个模态框的效果了。

保护自己的属性和方法

单例模式经常为我们提供一个命名空间。例如我们使用过的jQuery,单例模式就为它提供了一个命名空间jQuery。

 

 在上面的代码中,因为可用的单词有限,命名十分简单,但是如果后续后其他的同事在维护代码的时候,出现了同名的方法或变量,这里的业务逻辑就会出现问题,此时就需要用命名空间来约束每一个人定义的变量:

  

 由于对象中的this指代当前对象,所以,上面两种写法是等效的。

以上是关于JavaScript设计模式之单例模式的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript创建对象之单例工厂构造函数模式

JAVA SCRIPT设计模式--创建型设计模式之单例模式

JavaScript设计模式之单例模式

「设计模式」JavaScript - 设计模式之单例模式与场景实践

深入理解JavaScript系列(25):设计模式之单例模式

JavaScript之单例实战