TypeScriptでシングルトンパターンを実装するには、クラスを使った方式が一般的かと思います。
クラス内部でインスタンスを管理する変数を作って、そこに唯一のインスタンスを格納しておく方式です。
class Singleton { // クラスの唯一のインスタンスを保持するための静的プロパティ private static instance: Singleton; // コンストラクタをprivateにして外部からのインスタンス化を防ぐ private constructor() { // 初期化処理(必要に応じて) console.log('Singleton instance created'); } // シングルトンのインスタンスを取得するためのメソッド public static getInstance(): Singleton { if (!Singleton.instance) { Singleton.instance = new Singleton(); } return Singleton.instance; } // 他のメソッドやプロパティを定義可能 public someMethod(): void { console.log('Singleton method called'); } }
しかし、関数をメインにした書き方に慣れてしまうとクラスを使った方法は何かと不便です。
そこでクラスを使わないシングルトンの書き方をChatGPTに聞いたところ、IIFE (即時実行関数式)を使った書き方を教えてくれました。
下記は、メモリ上に配列を保存し、どこからでも参照できるインメモリDBの簡易版を提供する関数です。
const MemoryCache = (() => { // 唯一のインスタンスを保持するためのプロパティ let instance: any = null; const init = () => { // インスタンスの初期化処理。プライベートなメソッドやプロパティを定義 const myArray:string[] = []; return { // パブリックなメソッドやプロパティを定義 getData: () => myArray, setData: (input: string) => { myArray.push(input) } }; }; return { getInstance: () => { if (!instance) { instance = init(); } return instance; } }; })(); // 使い方 const memoryCache = MemoryCache.getInstance(); memoryCache.setData("hoge"); console.log(memoryCache.getData());
即時実行されることにより、getInstance関数にアクセス可能になり、実行することでインスタンスが無ければ生成され、既に存在すればそのインスタンスが返るのでシングルトンとして利用できます。
anyが気持ち悪い場合はinit内のreturnが返す関数が入ったオブジェクトの型を定義して指定することもできます。