web-dev-qa-db-ja.com

ES6シングルトンとクラスの1回のインスタンス化

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'

次のシングルトンパターンを使用することとの違いは何ですか?どちらか一方を使用する理由はありますか?実際、私が最初に挙げた例に気づいていない問題があるかどうかを知りたいと思っています。

シングルトンパターン:

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()
30
Aaron

違いは、物事をテストするかどうかです。

api.spec.jsテストファイルがあるとします。また、APIには、定数のように1つの依存関係があります。

具体的には、両方のバージョンのコンストラクターは、Constantsインポートという1つのパラメーターを取ります。

したがって、コンストラクタは次のようになります。

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?
    });
});

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

12
Zlatko

私はどちらもお勧めしません。これは完全に複雑です。オブジェクトが1つだけ必要な場合は、 class構文を使用しないでください !ただ行く

import Constants from '../constants';

export default {
  url: Constants.API_URL,
  getCities() {
    return fetch(this.url, { method: 'get' }).then(response => response.json());
  }
};
import API from './services/api-service'

または さらに簡単

import Constants from '../constants';

export const url = Constants.API_URL;
export function getCities() {
  return fetch(url, { method: 'get' }).then(response => response.json());
}
import * as API from './services/api-service'
34
Bergi

シングルトンパターンを使用するもう1つの理由は、一部のフレームワーク(Polymer 1.0など)でexport構文を使用できないことです。
だからこそ、2番目のオプション(シングルトンパターン)の方が便利です。

それが役に立てば幸い。

2
Peter

両方とも異なる方法です。以下のようなクラスをエクスポートします

const APIobj = new _API();
export default APIobj;   //shortcut=> export new _API()

そして、以下のように複数のファイルにインポートすると、同じインスタンスとシングルトンパターンの作成方法が指定されます。

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

クラスを直接エクスポートする他の方法は、インポートするファイルのようにシングルトンではありませんが、クラスを更新する必要があります。これにより、エクスポートクラスごとに個別のインスタンスが作成されます。

export default API;

クラスのインポートと更新

import API from './services/api-service';
let api = new API()
0
Sumer