内容简介:单例就是保证一个类只有一个实例,实现方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。但是有个问题:违反了单一职责原则,不够清晰,所以需要改进一下现在是清晰了,但是还有一个小问题,Window给写死了,作为一个优秀的程序员,肯定要灵活,来来再改进一下。
单例就是保证一个类只有一个实例,实现方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。
代码
单例模式的简单实现
es5
function Window(name) { this.name = name; } Window.prototype.getName = function () { return this.name; } //这是类上的方法,只可以通过类来访问,而不能通过实例来访问 Window.getInstance = (function () { let instance; return function (name) { if (!instance) { instance = new Window(name); } return instance; } })(); let w1 = Window.getInstance(); let w2 = Window.getInstance(); console.log(w1 === w2) // --> true 复制代码
es6
class Window { constructor(name) { this.name = name; } static getInstance() { if (!this.instance) { this.instance = new Window(); } return this.instance; } } let w1 = Window.getInstance(); let w2 = Window.getInstance(); console.log(w1 === w2) 复制代码
缺点:
- 客户端 就是使用这个类的使用者必须知道这是一个单例的类,必须主动调用getInstance方法,使用麻烦
- 并不能真正阻止客户端直接new Window
let w3 = new Window(); let w4 = new Window(); 复制代码
优化过程
透明单例
//透明单例 let Window = (function () { let window; let Window = function (name) { if (window) { return window; } else { this.name = name; return (window = this); } } return Window; })(); let w1 = new Window(); let w2 = new Window(); console.log(w1 === w2); 复制代码
- 创建一个this=空对象
- new 关键字,如果返回的是一个对象,那么返回对象
但是有个问题:违反了单一职责原则,不够清晰,所以需要改进一下
//把类的实例的创建逻辑和单例逻辑分开 function Window(name) { this.name = name; } Window.prototype.getName = function () { console.log(this.name); } let CreateWindow = (function () { let instance; return function (name) { if (!instance) { instance = new Window(name); } return instance; } })(); let w1 = new CreateWindow('zfpx1'); let w2 = new CreateWindow('zfpx2'); console.log(w1 === w2); 复制代码
现在是清晰了,但是还有一个小问题,Window给写死了,作为一个优秀的程序员,肯定要灵活,来来再改进一下。
function Window(name) { this.name = name; } Window.prototype.getName = function () { console.log(this.name); } let CreateWindow = (function () { let instance; return function (name) { if (!instance) { instance = new Window(name); } return instance; } })(); let w1 = new CreateWindow('zfpx1'); let w2 = new CreateWindow('zfpx2'); console.log(w1 === w2); 复制代码
命名空间
1.变量名冲突
2.复杂层次对象的可读性要求
其实我们之前用的jquery并没有把变量都声明在 window上,而是都挂在$对象 jQuery,来,栗子两枚:
$.get(); $.post(); $.ajax(); let $ = { ajax(){}, get(){}, post(){} } let $ = {}; $.define = function (namespace, fn) { let namespaces = namespace.split('.'); let fnName = namespaces.pop(); let current = $; for (let i = 0; i < namespaces.length; i++) { let namespace = namespaces[i];//dom if (!current[namespace]) { current[namespace] = {};//{dom:{}} } current = current[namespace]; } current[fnName] = fn; } $.define('dom.class.addClass', function () { console.log('dom.class.addClass'); }); $.define('dom.attr', function () { console.log('dom.attr'); }); $.define('string.trim', function () { console.log('string.trim'); }); console.log($) // define、dom、string都挂载上了了 $.dom.class.addClass('title'); // -> dom.class.addClass $.dom.attr('src'); // -> dom.attr $.string.trim(' abc '); // -> string.trim 复制代码
单例模式的应用场景
jQuery
只会有一个jQuery实例
if(window.jQuery!=null){ return window.jQuery; }else{ //init~~~~~~~ } 复制代码
模态窗口
一般网站都会有用户系统,例如我们去淘宝买东西,第一时间需要你先登录
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <button id="show-btn">显示登录框</button> <button id="hide-btn">隐藏登录框</button> <script> class Login { constructor() { this.element = document.createElement('div'); this.element.innerHTML = ( ` 用户名 <input name="username"/> 密码 <input name="password"/> <input type="submit" value="登录"/> ` ); this.element.style.cssText = `width:100px;height:100px;position:absolute;left:50%;top:50%;margin-top:-50px;margin-left:-50px;display:none`; document.body.appendChild(this.element); } show() { this.element.style.display = 'block'; } hide() { this.element.style.display = 'none'; } static getInstance() { if (!this.instance) { this.instance = new Login(); } return this.instance; } } document.getElementById('show-btn').addEventListener('click', function () { Login.getInstance().show(); }); document.getElementById('hide-btn').addEventListener('click', function () { Login.getInstance().hide(); }); </script> </body> </html> 复制代码
store
redux 整 个应用只有一个仓库,整 个仓库只有一个状态state
//redux 整 个应用只有一个仓库,整 个仓库只有一个状态state function createStore(reducer) { let state; let listeners = []; function subscribe(listener) { listeners.push(listener); } function getState() { return state; } function dispatch(action) { state = reducer(state, action); } return { getState, dispatch, subscribe } } let reducer = function () { } let store = createStore(reducer); 复制代码
今天写到这里,喜欢的可以点赞,同时欢迎抛转,有空再写下总结吧~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 设计模式——订阅模式(观察者模式)
- 设计模式-简单工厂、工厂方法模式、抽象工厂模式
- java23种设计模式-门面模式(外观模式)
- 设计模式-享元设计模式
- Java 设计模式之工厂方法模式与抽象工厂模式
- JAVA设计模式之模板方法模式和建造者模式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Learning Processing
Daniel Shiffman / Morgan Kaufmann / 2008-08-15 / USD 49.95
Book Description Teaches graphic artists the fundamentals of computer programming within a visual playground! Product Description This book introduces programming concepts in the context of c......一起来看看 《Learning Processing》 这本书的介绍吧!