<!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>