You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Back in 1994, a book was authored by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides that discusses 23 desgin patterns, titled Design Patterns: Elements of Resuable Object-Oriented Software. You may have heard of this book or the authors as Gang of Four (GoF).
varnamespace={getSingleton: (function(){// BEGIN iifevarsingletonreturnfunction(){if(!singleton){singleton={amethod: function(){console.log('amethod')},}}returnsingleton}})(),// END iife}// Invoke: namespace.getSingleton().amethod()
单例模式
单例模式(Singleton Pattern)是最简单的设计模式之一。这种类型的设计模式属于创建型 (Creational) 模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如线程池、全局缓存、浏览器中的 window 对象等。在 JavaScript 开发中,单例模式的用途同样非常广泛。试想一下,当我们单击登录按钮的时候,页面中会出现一个登录浮窗,而这个登录浮窗是唯一的,无论单击多少次登录按钮,这个浮窗都只会被创建一次,那么这个登录浮窗就适合用单例模式来创建。
关键点
意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当您想控制实例数目,节省系统资源的时候。
如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
关键代码:构造函数是私有的。
UML
我们将创建一个 SingleObject 类。SingleObject 类有它的私有构造函数和本身的一个静态实例。
SingleObject 类提供了一个静态方法,供外界获取它的静态实例。SingletonPatternDemo,我们的演示类使用 SingleObject 类来获取 SingleObject 对象。
ES5
面向对象
要实现一个标准的单例模式并不复杂,无非是用一个变量来标志当前是否已经为某个类创建过对象,如果是,则在下一次获取该类的实例时,直接返回之前创建的对象。代码如下:
我们通过 Singleton.getInstance 来获取 Singleton 类的唯一对象,这种方式相对简单,但有 一个问题,就是增加了这个类的“不透明性”,Singleton 类的使用者必须知道这是一个单例类, 跟以往通过 new XXX 的方式来获取对象不同,这里偏要使 Singleton.getInstance 来获取对象。
上面单例模式的实现,更多的是接近传统面向对象语言中的实现,单例对象从 “类” 中创建而来。在以类为中心的语言中,这是很自然的做法。比如在 Java 中,如果需要某个对象,就必须先定义一个类,对象总是从类中创建而来的。
class-free
但 JavaScript 其实是一门无类(class-free)语言,也正因为如此,生搬单例模式的概念并无意义。在 JavaScript 中创建对象的方法非常简单,既然我们只需要一个“唯一”的对象,为什 么要为它先创建一个“类” 呢?这无异于穿棉衣洗澡,传统的单例模式实现在 JavaScript 中并 不适用。
1.使用命名空间
适当地使用命名空间,并不会杜绝全局变量,但可以减少全局变量的数量。 最简单的方法依然是用对象字面量的方式:
2.使用闭包封装私有变量
这种方法把一些变量封装在闭包的内部,只暴露一些接口跟外界通信:
ES6
ES6 里有了模块和类的概念,实现起来会变得不一样:
Typescript
TypeScript 中有了
private
等概念,实现起来会更加有趣。让我们想象一下,我们想要一个跟踪温度的类。在这个系统中,我们希望有一个入口,可以改变温度。这就是 Singleton类 的样子:
上面的实现有一下几点需要注意:
如果使用 new 关键字创建对象:
根据上面的例子,我们也可以访问 temperature 属性。现在让我们设置温度值并将其增加/减少几次:
小结
在 java 中,单例模式根据是否 lazy loading (懒汉模式/饿汉模式)以及是否线程安全,分为很多种实现方式。而在 JS 中,我们不用关注线程安全的问题,因此无论是代码复杂度还是实现难度都会低很多。
参考
The text was updated successfully, but these errors were encountered: