[GoF] 單例模式 Singleton
Singleton example source code @ pjchender github
Singleton 的定義是「保證一個類別僅有一個實例,並提供一個存取它的全域存取點(JavaScript 設計模式與開發實踐)」。不同檔案匯入時也都拿到的是相同的實例。
class Singleton {
static instance: Singleton | null = null;
constructor(public name: string) {}
getName() {
console.log(this.name);
}
static getInstance(name: string) {
// 如果沒有被初始化過,就初始化一個
if (Singleton.instance === null) {
Singleton.instance = new Singleton(name);
}
return Singleton.instance;
}
}
const a = Singleton.getInstance('aaron1');
a.getName(); // aaron1
const b = Singleton.getInstance('aaron2');
b.getName(); // aaron1
console.log(a === b); // true
適合情境
- 需要確保整個 App 只會有一個該變數或方式時,例如,DB Connection、Global State
避免污染全域變數
使用 namespace
class MyApp {
static state: Record<string, any> = {};
static createNamespace = (path: string): void => {
const parts = path.split('.');
let current = MyApp.state;
for (const keyName of parts) {
if (current[keyName] === undefined) {
current[keyName] = {};
}
current = current[keyName];
}
};
static getNamespace = (path: string): any => {
const parts = path.split('.');
let current = MyApp.state;
for (const keyName of parts) {
if (current[keyName] === undefined) {
throw new Error(`There is no ${path} in the state`);
}
current = current[keyName];
}
return current;
};
static print = (): void => {
console.log(MyApp.state);
};
}
MyApp.createNamespace('people.name.firstName');
const people = MyApp.getNamespace('people');
console.log(people); // {"name": {"firstName": {}}
使用閉包(closure)
// 取得閉包回傳的內容
const user = (function () {
const _name = 'pjchender';
const _age = 29;
return {
getUserInfo() {
return `${_name} is ${_age}.`;
},
};
})();
const aaron = user.getUserInfo();
console.log(aaron);
ES Module 本身就是單例
// counter.js
export const counter = {
count: 1,
};
// file1.js
import { counter } from './counter.js';
counter.count++;
// file2.js
import { counter } from './counter.js';
counter.count++;
// main.js
import './file1.js';
import './file2.js';
import { counter } from './counter.js';
console.log(counter.count); // 3;