JavaScript设计模式之单例模式

161 阅读3分钟

两周没更新了啦,不是笔者懒,是加班真的有点emo😢...

最近朋友带着晚上有在跑步,感觉还是很不错的很精神,也遇到了一个让我很惊喜同理心很强的妹子,希望会有好的结果吧。

大佬带着做项目,感觉很多思想层面的东西自己还是有差距,有时候虽然在听,但是一些地方还是不能站在更高的层面去分析问题吧,学习设计模式的目的也在于此,希望自己在思想层面上,能够有一点提升吧。

此篇主要是针对于设计模式的的读书笔记,看书和自己理解以及在实际项目中运用,这是三件事。

1.单例模式:

定义:保证一个类只有1个实例,并提供一个访问他的全局访问点。

下面呢,来看下单例模式的实现:

	var Singleton = function( name ){
		this.name = name;
		this.instance = null;
	};

	Singleton.prototype.getName = function(){
		alert ( this.name );
	};

	Singleton.getInstance = function( name ){
		if ( !this.instance ){
			this.instance = new Singleton( name );
		}
		return this.instance;
	};

	var a = Singleton.getInstance( '科比' );
	var b = Singleton.getInstance( '艾弗森' );
  • Singleton为构造函数,接受一个name参数
  • Singleton添加一个原型方法getName
  • Singleton通过getInstance方法来获取类的实例,如果有就返回实例,没有就新建一个并赋值给this.instance

上面的这种方式呢,通过上面这种方式,使用者无法知道这个类是一个单例类,换言之就是所谓的不透明性

那么如何减低他的这种不透明性,让使用者知道消除疑虑呢?接着来看下下面的例子

	var CreateDiv = (function(){
		var instance;
		var CreateDiv = function( html ){
			if ( instance ){
				return instance;
			}
			this.html = html;
			this.init();
			return instance = this;
		};
		CreateDiv.prototype.init = function(){
			var div = document.createElement( 'div' );
			div.innerHTML = this.html;
			document.body.appendChild( div );
		};
		return CreateDiv;
	})();

	var a = new CreateDiv( 'sven1' );
	var b = new CreateDiv( 'sven2' );
	alert ( a === b ); // true
  • JavaScript是通过函数的来实现封闭作用域的,这里为了把interface封装起来,就得包装一个壳,也就是自执行函数+闭包的形式。

但是通过上面的这种自执行函数+闭包的方式确实是可以减少不透明性,但是存在另外一个问题,如果说以后要修改,不是创建一个实例,而是很多个实例,那么修改上面代码的成本比较高,这又如何解决呢?

代理单例模式:

	var CreateDiv = function( html ){
		this.html = html;

		this.init();
	};
	// 初始化方法挂载到原型上
	CreateDiv.prototype.init = function(){
		var div = document.createElement( 'div' );
		div.innerHTML = this.html;
		document.body.appendChild( div );
	};
	
	var ProxySingletonCreateDiv = (function(){
		var instance;
		return function( html ){
			if ( !instance ){
				instance = new CreateDiv( html );
			}
			return instance;
		}
	})();

	var a = new ProxySingletonCreateDiv( '科比' );
	var b = new ProxySingletonCreateDiv( '艾弗森' );
	alert ( a === b );
  • CreateDiv构造函数,然后为其原型上添加一个init初始化方法
  • ProxySingletonCreateDiv是个返回一个匿名函数的自执行函数,这个匿名函数也是通过闭包来判断是否是已经有实例了。
  • 将判断单例的部分通过代理模式抽离出来进行独立,那么这样日后如果想要通过这个类去创建很多个单例的时候,也是没有问题的。

2.惰性单例:

提起惰性,第一个想到的就是懒,懒加载啊等等,就是你需要我的时候,我才出来,不需要我,我就躺平😑。

惰性单例也是顾名思义,在需要的时候才创建对象实例。这种技术在实际开发过程中是灰常实用的。

	Singleton.getInstance = (function(){
		var instance = null;
		return function( name ){
			if ( !instance ){
				instance = new Singleton( name );
			}
			return instance;
		}
	})();
  • 这里其实也是一样的,自执行函数+闭包,实现在需要的时候创建单例。

最后的最后,祝愿所有的程序员,都可以摆脱加班,像海贼王路飞那样,做个最自由的存在。