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