JS学习十六天----单例模式

来源:互联网 发布:网络电影不可抗力 编辑:程序博客网 时间:2024/06/03 11:34

单例模式

说实话,今天本来不想写博客的,但是思前想后,与其看看片,不如打打字(),还是写一点吧,不多写个最简单的的,别看简单,但是很常用啊!

今天发现了一个好东西叫做基维百科,我在里面看到了关于单例模式的一点小小的介绍,因为本屌不是很喜欢抄写概念啥的,但是百科里面说的还不错,给你们抄过来:

在应用单例模式时,生成单例的类必须保证只有一个实例的存在,很多时候整个系统只需要拥有一个全局对象,才有利于协调系统整体的行为.比如在整个系统的配置文件中,配置数据有一个单例对象集进行统一读取和修改,其他对象需要配置数据的时候也统一通过单例对象来获取配置数据,这样就可以简化复杂环境下的配置管理.

 

单例模式的思路:一个类能返回一个对象的引用(并且永远是同一个)和一个获得该势力的方法(静态方法,通常使用GetInstance名称).那么当我们调用这个方法时,如果类持有的引用不为空就返回该引用,否则就创建该类的实例,并且将实例引用赋值给该类保持的那个引用再返回.同时将该类的构造函数定义为私有的,避免其他函数使用该构造函数来实例化对象,只通过该类的静态方法来得到该类的唯一实例.

 

 

对于JS来说,巨大的灵活性使得可以有很多种方式实现单例模式,使用闭包来模拟私有数据,按照其思路可得(不知道闭包是啥玩意的自己去百科):

var single=(function(){

var unique;

function GetInstance(){

if(unique==undefined){

unique=new Construct();

}

return unique;

}

function Construct(){

//生成但里的构造函数的代码

}

return {

GetInstance:GetInstance

}

})();

分析:unique便是返回对象的引用,GetInstance便是静态方法获得实例.Construct便是创建实例的构造函数.可以通过single.GetInstance()来获取到单例,并且每次调用均获取到同一个单例.这就是单例模式所实现的效果.

 

JS的语言风格是相当的灵活,以上实现的方式显然很笨重,既然JS有它自己的优势,那么咱们就可以利用JS的优势来实现单例模式.

 

 

实现1:最简单的对象字面量

var singleton={

attr:1,

method : function(){return this.attr;}

}

var t1=singleton;

var t2=singleton;

alert(t1==t2);//true

分析:简单易用,缺点是没有体现面向对象封装的有点,,所有的属性方法都是暴露的.对于一些需要使用私有变量的情况就显得心有余而力不足的了.当然在对于this的问题上也有一定的弊端.

 

 

 

 

实现2:构造函数内部判断

function Construct(){

//确保只有单例

if(Construct.unique!==undefined){

return Construct.unique;

}

//其他代码

this.name="syx";

this.age="22";

Construct.unique=this;

}

var t1=new Construct();

var t2=new Construct();

alert(t1==t2);//也是true

分析:也是简单,无非就是提出一个属性来做判断,但是该方式也没有什么安全性,一旦我在外部修改了Constructunique属性,那么单例模式也就破坏了.

 

 

实现3:闭包方式

对于举着灵活大旗的JS来手,任何问题都能找到n中答案,只不过让我自己去掂量孰优孰劣而已,下面简单的举几个使用闭包实现单例模式的方式,无非也就是将创建了的单例缓存而已.

var single=(function(){

var unique;

function Construct(){

//生成单例的构造函数的代码

}

unique=new Construct();

return unique;

})();

 

只要每次将var t1=single;var t2=single;即可.与对象字面量方式类似.不过相对而言更安全一些,当然也不是绝对的.

如果希望会用调用single()方式使用,那么也只需要将内部的return改为 :return function(){

return unique;

}

以上方式也可以使用new的的方式来进行.当然这便这时给出了必报的一种案例而已,也可以在Construct中判断单例是否存在等等.各种方式在各个不同情况做好选择即可.

 

 

总结

单例模式相对而言是各大模式中比较简单的,但是单例模式也是最常用并且很有用的.JS中尤为突出(每个对象字面量都可以看做是一个单例).

记住,是否严格的只需要一个实例对象的类(虽然JS没有类的概念),那么就要考虑使用单例.

使用数据缓存来存储该单例,用作判断单例是否已经生成,是单例模式主要的实现思路.

 

 

扩展一下闭包的概念:

什么是闭包?
“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
相信很少有人能直接看懂这句话,因为他描述的太学术。我想用如何在Javascript中创建一个闭包来告诉你什么是闭包,因为跳过闭包的创建过程直接理解闭包的定义是非常困难的。看下面这段代码:
function a(){
var i=0;
function b(){
alert(++i);
}
return b;
}
var c = a();
c();
这段代码有两个特点:
1、函数b嵌套在函数a内部;
2、函数a返回函数b
这样在执行完var c=a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:
当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。

闭包有什么作用?
简而言之,闭包的作用就是在a执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量。这是对闭包作用的非常直白的描述,不专业也不严谨,但大概意思就是这样,理解闭包需要循序渐进的过程。
在上面的例子中,由于闭包的存在使得函数a返回后,a中的i始终存在,这样每次执行c()i都是自加1alerti的值。
那么我们来想象另一种情况,如果a返回的不是函数b,情况就完全不同了。因为a执行完后,b没有被返回给a的外界,只是被a所引用,而此时a也只会被b引用,因此函数ab互相引用但又不被外界打扰(被外界引用),函数ab就会被GC回收。

闭包的应用
1、保护函数内的变量安全。以最开始的例子为例,函数ai只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。
2、在内存中维持一个变量。依然如前例,由于闭包,函数ai的一直存在于内存中,因此每次执行c(),都会给i自加1
以上两点是闭包最基本的应用场景,很多经典案例都源于此。

 

 

觉得我写的对你多少有点帮助的话,给个好评哦,(づ ̄3)づ╭❤~

0 0
原创粉丝点击