1. ホーム
  2. javascript

[解決済み] ES6 シングルトン vs クラスの一度のインスタンス化

2023-04-22 03:36:42

質問

ES6クラスを使ってシングルトンパターンを使用するパターンを見かけますが、ファイルの一番下でクラスをインスタンス化し、そのインスタンスをエクスポートするだけではなく、なぜそれを使うのか不思議に思っています。このようなことをすると、何か否定的な欠点があるのでしょうか。たとえば

ES6 エクスポートインスタンスです。

import Constants from '../constants';

class _API {
  constructor() {
    this.url = Constants.API_URL;
  }

  getCities() {
    return fetch(this.url, { method: 'get' })
      .then(response => response.json());
  }
}

const API = new _API();
export default API;

使用方法です。

import API from './services/api-service'

以下のSingletonパターンを使用するのと何が違うのでしょうか?また、どちらかを使用する理由はありますか?実は、私があげた最初の例には、私が気づいていない問題がある可能性があるのかどうか、もっと知りたいと思っているのです。

シングルトン パターン。

import Constants from '../constants';

let instance = null;

class API {
  constructor() {

    if(!instance){
      instance = this;
    }

    this.url = Constants.API_URL;

    return instance;
  }

  getCities() {
    return fetch(this.url, { method: 'get' })
      .then(response => response.json());
  }
}

export default API;

使用方法。

import API from './services/api-service';

let api = new API()

どのように解決するのですか?

違いは、いろいろとテストしたい場合です。

例えば、あなたが api.spec.js というテストファイルがあるとします。そして、あなたのAPIは、これらの定数のような、1つの依存関係を持っています。

具体的には、両方のバージョンでコンストラクタは1つのパラメータ、あなたの Constants インポートです。

というわけで、コンストラクタはこんな感じです。

class API {
    constructor(constants) {
      this.API_URL = constants.API_URL;
    }
    ...
}



// single-instance method first
import API from './api';
describe('Single Instance', () => {
    it('should take Constants as parameter', () => {
        const mockConstants = {
            API_URL: "fake_url"
        }
        const api = new API(mockConstants); // all good, you provided mock here.
    });
});

さて、インスタンスのエクスポートでは、モッキングはありません。

import API from './api';
describe('Singleton', () => {
    it('should let us mock the constants somehow', () => {
        const mockConstants = {
            API_URL: "fake_url"
        }
        // erm... now what?
    });
});

インスタンス化されたオブジェクトがエクスポートされた状態では、(簡単かつ健全に)その動作を変更することはできません。