js设计模式——单体模式

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>测试文档</title>
    <script>
//        单体模式的定义:一个只能实例化一次的类,并且提供一个众所周知的全局访问点。
//        单体模式的作用:面向对象编程的思考方式,就是对现实生活的具体对象抽象化。————即建模
// 对于现实生活来说,很多对象只有一个是很重要的。比如说,一个公司只能有一个会计系统,一个数字滤波器只能有一个模数转换器
//一台计算机只应该有一个文件系统和窗口管理器。对应到抽象的面向对象编程的世界里,就是有些类只应该有一个实例。
//        单体模式的实现:让类自身负责保存它的唯一实例。(这个类可以保证只能创建一个实例,并且有一个可访问该实例的方法)
//
//        单体模式在js中的实现有两种方式。一,对象字面量。二,闭包。

//
//        方式一:使用对象字面量形式的单体
//在js中没有类的概念。js是通过对象实例化对象的。
//因此,你可以把Singleton看作是一个类,并且实现了一个唯一的对象。(可能有点绕)
//此外,我们可以通过Singleton.name,Singleton.getName等点操作符来实现对实例的访问。
//        对象字面量创建的单体的应用。                        ————封装
//                                  封装————命名空间的使用
//通过将数据和方法都封装在一个对象内部
//这样就保护了外部的同名变量不会被意外重写。当本地代码作为第三方js库使用时也不会影响对方的本地代码的变量。————命名空间的作用

//      假设这是加载第三方js库内定义的变量
        var name='Elvis';
//        本地js代码
        var Singleton={
            name:'Byronvis',
            getName:function(){
                alert( this.name);//有时候会出错
                alert(Singleton.name);//最好使用这种方式
            }
        };
        Singleton.getName();

//        不使用单体模式的情况下很容易意外重写变量

//      假设这是加载第三方js库内定义的变量
        var name="Elvis";
//        本地js代码
        var name='Byronvis';//意外重写了第三方js库的对象
        var getName=function(){
            alert(name);
        };
        getName();

//                                  封装————代码包装器
//在拥有许多网页的网站中,有些js代码是所有网页都需要的,它们通常都放在独立的文件中,
//而有些代码是某个网页专用的,不会被用到其他地方。最好把这两种代码分别包装在自己的单体中。
//换句话说,就是可以把几个不常用的功能块封装在一个单体中。

//        方式二:通过闭包创建单体。
//之前通过对象字面量创建的单体有一些缺点。就是单体对象的数据和方法都是公有的,没有私有属性。

//通过闭包就可以实现对象的私有属性。
        SecondSingleton=(function(){
//            对象的私有数据
            var name='Elvis';
//            对象的私有方法
            function setName(){
                name='Byron'
            }
            return {
//                对象的公有数据
                location:'Hangzhou',
//                对象的特权方法
                getLocation:function(){
                    alert(this.location);
                },
                getName:function(){
                    alert(name);
                }
            };
        })();
        SecondSingleton.getName();


//      闭包方式创建单体的应用。                            ————分支
//分支的作用:
//浏览器之间是有差异的。针对于某个功能,不同的浏览器有不同的实现方式
//我们把每个浏览器的实现方式进行封装,并在页面加载js文件时,通过能力测试或者浏览器嗅探来动态决定使用哪种方式实现该功能。

  _SecondSingleton=(function(){
            var objA={
                age:22,
                getAge:function(){
                    alert('age:'+this.age);
                }

            };
            var objB={
                age:23,
                getAge:function(){
                    alert(this.age);
                }
            };
//            约束条件,实现分支的根本
            return (2>1)?objA:objB;
        })();
        _SecondSingleton.getAge();

 
//        惰性实例化单体
//之前两种方式创建的单体,都有一个共同点,当网页加载好js文件后会立即实例化单体。
// (源于对象字面量方式直接在全局环境中定义,闭包方式的函数也是定义后立即执行)
//对于单体实例比较大的单体,我们有时候希望其在使用时实例化,不希望过早实例化占用资源。
//这时候就需要惰性实例化单体了。
//        惰性实例化单体的思路:将构造器函数封装起来,通过一个外部接口函数延迟返回构造器
//将实例的构造器这个闭包外层再包围一个闭包。
//通过外层闭包的特权方法实现对构造器的控制。
//此时访问单体的属性方法就发生了改变。
//由此也可以看出惰性实例化单体的主要缺点就是复杂。不如前两种来的直观些。

 ThirdSingleton=(function() {
//          用于保存实例的私有变量
            var instance;
            return{
//                调用实例化方法(通过这个方法实现对实例化单体的时间控制)
                getInstance:function(){
//                    若实例不存在则实例化对象
                    if(!instance){
                        instance=Constructor();
                    }
//                    若实例存在则返回实例
                    return instance;
                }

            };
            //单体实例的构造器
            function Constructor() {
//                对象的私有数据
                var name = 'Elvis';
//                对象的私有方法
                function setName() {
                    name = 'Byron'
                }

                return {
//                对象的公有数据
                    location: 'Hangzhou',
//                对象的特权方法
                    getLocation: function () {
                        alert(this.location);
                    },
                    getName: function () {
                        alert(name);
                    }
                }
            }
        })();
//      访问单体的属性的方法改变,必须有getInstance()前缀
        ThirdSingleton.getInstance().getLocation();

 

  </script>
</head>
<body>
这真的只是一个测试文档啊。
</body>
</html>

原文地址:https://www.cnblogs.com/byronvis/p/4168177.html