- Mastering JavaScript Design Patterns
- Simon Timms
- 714字
- 2021-08-05 17:14:59
Singleton
The Singleton pattern is perhaps the most overused pattern. It is also a pattern that has fallen out of favor in recent years. To see why people are starting to advise against using Singleton, let's take a look at how the pattern works.
Singleton is used when a global variable is desirable, but Singleton provides protection against accidentally creating multiple copies of a complex object. It also allows for the deferral of object instantiation until the first use.
The UML diagram for Singleton is as follows:

It is clearly a very simple pattern. The Singleton pattern acts as a wrapper around an instance of the class and the Singleton itself lives as a global variable. When accessing the instance, we simply ask Singleton for the current instance of the wrapped class. If the class does not yet exist within the Singleton, it is common to create a new instance at that time.
Implementation
Within our ongoing example in the world of Westeros, we need to find a case where there can only ever be one of an item. Unfortunately, it is a land with frequent conflicts and rivalries, and so my first idea of using the king as the Singleton pattern is simply not going to fly. This split also means that we cannot make use of any of the other obvious candidates (capital city, queen, general…) as there may be many instances of each of those too. However, in the far north of Westeros, there is a giant wall constructed to keep an ancient enemy at bay. There is only one of these walls and it should pose no issue having it in the global scope.
Let's go ahead and create a Singleton class in JavaScript:
var Westeros; (function (Westeros) { var Wall = (function () { function Wall() { this.height = 0; if (Wall._instance) return Wall._instance; Wall._instance = this; } Wall.prototype.setHeight = function (height) { this.height = height; }; Wall.prototype.getStatus = function () { console.log("Wall is " + this.height + " meters tall"); }; Wall.getInstance = function () { if (!Wall._instance) { Wall._instance = new Wall(); } return Wall._instance; }; Wall._instance = null; return Wall; })(); Westeros.Wall = Wall; })(Westeros || (Westeros = {}));
The code creates a lightweight representation of the Wall
class. The Singleton pattern is demonstrated in the two highlighted sections. In a language like C# or Java, we would normally just set the constructor to be private so that it could only be called by the static getInstance
method. However, we don't have that ability in JavaScript: constructors cannot be private. Thus, we do the best we can and return the current instance from the constructor. This may appear strange, but in the way we've constructed our classes the constructor is no different from any other method, so it is possible to return something from it.
In the second highlighted section, we set a static variable, _instance
, to be a new instance of Wall
when one is not already there. In the case that _instance
already exists, we return that. In C# and Java, there will be a need for some complicated locking logic in this function to avoid race conditions as two different threads attempt to access the instance at the same time. Fortunately, there is no need to worry about this in JavaScript, where the multithreading story is different.
Disadvantages
Singletons have gained a somewhat bad reputation in the last few years. They are, in effect, glorified global variables. As we've discussed, global variables are ill conceived and the potential cause of numerous bugs. They are also difficult to test with unit tests, as the creation of the instance cannot easily be overridden. The single largest concern I have with them is that singletons have too much responsibility. They control not just themselves but also their instantiation. This is a clear violation of the single responsibility principle. Almost every problem that can be solved by using a Singleton pattern is better solved using some other mechanism.
JavaScript makes the problem even worse. It isn't possible to create a clean implementation of the Singleton pattern due to the restrictions on the constructor. This, coupled with the general problems around the Singleton pattern, lead me to suggest that this pattern should be avoided in JavaScript.
- UNIX編程藝術
- Instant Testing with CasperJS
- Node.js Design Patterns
- 精通網絡視頻核心開發技術
- The Complete Coding Interview Guide in Java
- Instant Nancy Web Development
- ElasticSearch Cookbook(Second Edition)
- Domain-Driven Design in PHP
- 深入實踐Kotlin元編程
- OpenMP核心技術指南
- 現代C:概念剖析和編程實踐
- 測試工程師Python開發實戰
- Practical Time Series Analysis
- Learning PrimeFaces Extensions Development
- Java語言GUI程序設計