保證一個類僅有以一個實例,僅能被實例化/建立一次,並提供全局的訪問點。javascript
單例模式是一種重要的設計模式,有些對象咱們只須要建立一個,好比瀏覽器的window對象,模態對話框。實現這種設計模式其實很簡單,最重要的是在建立實例的時候,用一個標記變量判斷實例是否已經建立。html
function Singleton(name){ this.name = name; this.instance = null; } Singleton.prototype.getName = function(){ console.log('name: ' + this.name); return this.name; } Singleton.getInstance = function(name){ if(!this.instance){ this.instance = new Singleton(name); } return this.instance; } var a = Singleton.getInstance('a'); var b = Singleton.getInstance('b'); alert(a === b);
點評:
該寫法不透明,使用者必須知道用Singleton.getInstance
獲取單例,而非經過更加通用的方法new xxx
方式。java
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 SingletonDiv = (function(){ var instance; return function(html){ if(!instance){ instance = new CreateDiv(html); } return instance; } })() var a = SingletonDiv('yyh'); var b = SingletonDiv('yyh1');
點評:
使用代理類+普通的類,使得職責分明。普通類負責實現基本功能,代理類管理單例。CreateDiv能夠直接生產一個實例,而加上代理,能夠實現單例。有木有一種模塊拼湊的快感,這就實現了低耦合。設計模式
在ES6中,能夠使用static方法代替閉包存儲單例。瀏覽器
class Singleton { constructor(name) { this.name = name; } static getInstance(name) { if(!Singleton.instance) { Singleton.instance = new Singleton(name) } return Singleton.instance; } getName() { return this.name; } } const singletonA = Singleton.getInstance('yyh1'); const singletonB = Singleton.getInstance('yyh2'); console.log(singletonA === singletonB); console.log(singletonA.getName() === singletonB.getName());
點評:ES6的靜態方法,和閉包同樣能在減小全局變量污染的同時,使標記變量更加長久的保存在內存中不被回收。閉包
// 負責建立DIV的基本功能 class CreateDiv { constructor(html) { this.html = html; this.init(); } init() { const div = document.createElement('div'); div.innerHTML = this.html; document.body.appendChild(div); } } // 負責管理單例 class ProxysingletonCreateDiv { constructor(htmlStr) { return ProxysingletonCreateDiv.getInstance(htmlStr); } static getInstance(name) { if(!ProxysingletonCreateDiv.instance) { ProxysingletonCreateDiv.instance = new CreateDiv(name) } return ProxysingletonCreateDiv.instance; } } const singletonC = new ProxysingletonCreateDiv('yyh1'); const singletonD = new ProxysingletonCreateDiv('yyh2'); console.log(singletonC === singletonD); singletonC.init(); singletonD.init();