Все программисты должны быть знакомы с шаблонами проектирования. Один из самых известных и распространенных - шаблон singleton. Если вы хотите понять этот шаблон и то, как его использовать с Node.JS, прочтите это быстрое и простое руководство.

Немного теории

Нам нужен синглтон, когда мы хотим убедиться, что существует только один экземпляр объекта. Поэтому вместо создания нового объекта нам нужно убедиться, что конструктор вызывается только один раз, а затем мы повторно используем экземпляр.

Мы можем добиться этого, реорганизовав наш класс, чтобы он имел:

  • скрытый (частный) constructor
  • общедоступный getInstance метод, который возвращает экземпляр класса

Теоретическая часть закончена. Приступим к программированию!

Шаблон Singleton

Сначала создадим Singleton.js файл:

class PrivateSingleton {
    constructor() {
        this.message = 'I am an instance';
    }
}
class Singleton {
    constructor() {
        throw new Error('Use Singleton.getInstance()');
    }
    static getInstance() {
        if (!Singleton.instance) {
            Singleton.instance = new PrivateSingleton();
        }
        return Singleton.instance;
    }
}
module.exports = Singleton;

Как мы видим, мы фактически создали два класса PrivateSingleton иSingleton. Это уловка, позволяющая скрыть (создать псевдоприватный) конструктор в классе Singleton.

Таким образом, если мы вызовем const object = new Singleton(), мы получим ошибку: Use Singleton.getInstance(). Однако, если мы вызовем Singleton.getInstance(), мы получим экземпляр, как и ожидалось. Если экземпляра еще нет, мы вызовем конструктор «private» класса PrivateSingleton и вернем экземпляр. В противном случае, если экземпляр уже существует, мы просто возвращаем его.

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

Затем мы можем создать simpletest.jsfile:

const Singleton = require('./Singleton');
const object = Singleton.getInstance(); 
console.log(object.message);   // Prints out: 'I am an instance'
object.message = 'Foo Bar';    // Overwrite message property
const instance = Singleton.getInstance();
console.log(instance.message); // Prints out: 'Foo Bar'

Все работает как положено! Технически на этом Node.JS и одноэлементная часть готовы. Однако ... есть еще кое-что ...

Кешированный синглтон

Воспользуемся механизмом кеширования модулей Node.JS:

Модули кэшируются после первой загрузки. Это означает (среди прочего), что каждый вызов require (‘foo’) будет возвращать один и тот же объект, если он будет разрешаться в один и тот же файл.

Как это работает на практике? Давайте реорганизуем наш Singleton класс:

class Singleton {
    constructor() {
        this.message = 'I am an instance';
    }
}
module.exports = new Singleton();

Это выглядит намного проще! Мы можем даже подумать, что это слишком просто и не существует getInstance() метода. В чем дело?

Важной частью является последняя строка, в которой мы не экспортируем класс module.exports = Singleton;, а вместо этого экспортируем экземпляр класса module.exports = new Singleton(). Node.JS будет кэшировать и повторно использовать один и тот же объект каждый раз, когда это потребуется.

Затем нам просто нужно выполнить простое обновление до test.js и удалить также getInstance:

const Singleton = require('./Singleton');
const object = Singleton;
console.log(object.message); // Prints out: 'I am an instance'
object.message = 'Foo Bar'; // Overwrite message property
const instance = Singleton;
console.log(instance.message); // Prints out: 'Foo Bar'

Вуаля! Оно работает. Отметим, что нам не нужно звонить new Singleton(). Мы просто повторно используем один и тот же объект.

Заключение

Создать синглтон в Node.JS очень просто. Когда мы используем кеширование Node.JS, это тривиально. В этой статье мы показали два способа достижения тех же результатов, и я настоятельно рекомендую использовать последний.

Пожалуйста, помните, что есть и другие шаблоны проектирования. Если вы хотите узнать больше о программировании, просмотрите другие мои руководства и следуйте за мной.

Если вам понравилась эта статья, ознакомьтесь, пожалуйста, с другими моими учебниками по программированию:
Node.JS и Factory Pattern
Понимание замыканий JavaScript
и многие, многие другие…