ES6 Singleton против создания экземпляра класса один раз

Я вижу шаблоны, которые используют шаблон singleton с использованием классов 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()

Ответ 1

Разница в том, что если вы хотите что-то проверить.

Скажем, у вас есть тестовый файл api.spec.js. И что у вашего API есть одна зависимость, как у этих констант.

В частности, конструктор в обеих ваших версиях принимает один параметр, ваш 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?
    });
});

С экспортированным экземпляром объекта вы не можете (легко и разумно) изменить его поведение.

Ответ 2

Я бы не рекомендовал. Это совершенно сложно. Если вам нужен только один объект, не использовать синтаксис 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'

Ответ 3

Другая причина использования Singleton Pattern - в некоторых средах (например, Polymer 1.0) вы не можете использовать синтаксис export.
Поэтому второй вариант (шаблон Singleton) более полезен для меня.

Надеюсь, это поможет.

Ответ 4

Оба делают то же самое. Первый - 100% es6. Второй - это старый способ, просто переписанный в es6.

Я бы пошел с первым в любое время, новые разработчики не поймут, почему вам пришлось усложнять вещи, если es6 - это то, с чего они начали в первую очередь

Ответ 5

Оба это разные способы. Экспорт класса, как показано ниже

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

а затем импорт, как показано ниже в нескольких файлах, будет указывать на один и тот же экземпляр и способ создания шаблона Singleton.

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

Принимая во внимание, что другой способ экспорта класса напрямую не одноэлементный, как в файле, куда мы импортируем, нам нужно обновить класс, и это создаст отдельный экземпляр для каждого обновления Экспортировать только класс:

export default API;

Импорт класса и обновление

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