但遗憾的是,以上的代码不能禁止用户直接实例化Singleton类。例如,通过以下语句实例化Singleton类仍然是成立的:
var instA =new Singleton ();
而随后你调用如下语句也是成立的:
alert(typeof(instA));
alert(instA.property1);
alert(instA.property1);
因此,我们需要进一步修改Singleton类的构造函数,使得Singleton类只能在Singleton.getInstance方法中进行实例化。
function Singleton(){
if(Singleton.caller!=Singleton.getInstance){
throw new Error(”Can not new Singleton instance!”);
}
…………
}
if(Singleton.caller!=Singleton.getInstance){
throw new Error(”Can not new Singleton instance!”);
}
…………
}
这样当用户试图自己创建多个对象的时候,通过人工抛出异常来阻止。不过这么做你感觉是不是还是有一点别扭?创建单例就创建单例吧,干嘛非要抛出一个异常呢?但无论如何,使用上述方案已经能够实现了仅能创建类的单例的目的。
下面,我们来讨论第三种方法(也是最优秀的方法)。这种方法巧妙利用了JavaScript对于“匿名”函数的支持特征来间接实现禁止对Singleton类构造函数的访问,从而较好地模拟了私有构造函数的特性,最终比较完美地解决了用JavaScript实现Singleton模式的问题。
列表2:借助于“匿名”函数的支持在JavaScript中创建Singleton模式类
<script type="text/javascript">
(function(){
//SingletonFactory Interface
SingletonFactory = {
getInstance : getInstance
}
//private classes
function SingletonObject()
{
SingletonObject.prototype.methodA = function()
{
alert('methodA');
}
SingletonObject.prototype.methodB = function()
{
alert('methodB');
}
SingletonObject.instance = this;
}
//SingletonFactory implementions
function getInstance()
{
if(SingletonObject.instance == null)
return new SingletonObject();
else
return SingletonObject.instance;
}
})();
var instA = null;
try
{
alert("试图通过new SingletonObject()构造实例!");
instA = new SingletonObject();
}
catch(e){
alert("SingletonObject构造函数不能从外部访问,系统抛出了异常!");
}
instA = SingletonFactory.getInstance(); //通过Factory上定义的静态方法获得
var instB = SingletonFactory.getInstance();
instA.methodA();
instB.methodA();
alert(instA == instB); //成功
</script>
(function(){
//SingletonFactory Interface
SingletonFactory = {
getInstance : getInstance
}
//private classes
function SingletonObject()
{
SingletonObject.prototype.methodA = function()
{
alert('methodA');
}
SingletonObject.prototype.methodB = function()
{
alert('methodB');
}
SingletonObject.instance = this;
}
//SingletonFactory implementions
function getInstance()
{
if(SingletonObject.instance == null)
return new SingletonObject();
else
return SingletonObject.instance;
}
})();
var instA = null;
try
{
alert("试图通过new SingletonObject()构造实例!");
instA = new SingletonObject();
}
catch(e){
alert("SingletonObject构造函数不能从外部访问,系统抛出了异常!");
}
instA = SingletonFactory.getInstance(); //通过Factory上定义的静态方法获得
var instB = SingletonFactory.getInstance();
instA.methodA();
instB.methodA();
alert(instA == instB); //成功
</script>
上面的第三种创建方式可谓挖空心思,穷JavaScript之能事,但终于获取了令人满意的效果。