РЕДАКТИРОВАТЬ: Я понял, что мое именование немного сбивает с толку, так как я использовал Container для представления контейнера IoC, а затем понял, что вы использовали это имя для представления вашего Singleton.
При условии, что вы можете создать экземпляр своего синглтона в центральной точке кода (например, файл точки входа при настройке сервера). Вы можете достичь Синглтона несколькими способами. Например:
let instance = null;
class Singleton {
constructor(arg1, arg2) {
this.arg1 = arg1;
this.arg2 = arg2;
}
}
module.exports = (...args) => {
return instance || (instance = new Singleton(...args));
}
Вы можете сделать это множеством способов, например, со статическими функциями вместо анонимной функции. Тем не менее, со всем этим я думаю, что становится немного запутанным относительно того, инициируете ли вы экземпляр или просто пытаетесь получить его.
Шаблоны контейнеров IoC (часто используемые в проектах C #), на мой взгляд, немного чище. Где у вас может быть один контейнерный класс, который отслеживает ваши синглтоны и обеспечивает отдельные функции доступа и инициализации.
class Container {
constructor() {
this.instances = {};
}
add(name, instance) {
this.instances[name] = instance; // depends if you want overwrite or not
}
get(name) {
if (!this.instances[name]) {
throw new Error('some appropriate error messaging for your app');
}
return this.instances[name];
}
remove(name) {
delete this.instances[name];
}
}
module.exports = new Container(); // this has to be a no-param constructor
Затем в коде инициализации вашего приложения вы инициализируете синглтоны и регистрируете их в своем контейнере:
const Container = require('<path_to_Container>');
const Singleton = require('<path_to_Singleton>');
...
Container.add('mySingleton', new Singleton(arg1, arg2));
и доступ к нему в любое время с помощью:
Container.get('mySingleton');
Пара замечаний:
- Вы можете использовать Singleton.name вместо строкового имени (в нашем примере mySingleton)
- Это всего лишь личное предпочтение. Но мне это нравится, потому что это кажется более декларативным, вы регистрируете (добавляете) экземпляр в контейнер при запуске приложения и не стираете границы между инициализацией и использованием. А это значит, что если вы добавите больше этих синглетонов в будущем, у вас уже есть один шаблон для этого.