Написание одноэлементного декоратора для использования с любым классом

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

Реальным примером может быть класс подключения к базе данных. Вы не захотите иметь несколько объектов базы данных, потому что изменения в одном из них могут сделать другие несогласованными.

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

В Python есть несколько синглтонов, которые вы часто используете, в том числе None, True и False. Тот факт, что None является синглтоном, позволяет вам сравнивать None с помощью ключевого слова is.

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

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

Теперь создайте класс подключения к базе данных:

@Singleton
class DBConnection(object):

    def __init__(self):
        """Initialize your database connection here."""
        pass

    def __str__(self):
        return 'Database connection object'

Давайте получим доступ к этому классу подключения:

c1 = DBConnection.Instance()
c2 = DBConnection.Instance()

print("Id of c1 : {}".format(str(id(c1))))
print("Id of c2 : {}".format(str(id(c1))))

print("c1 is c2 ? " + str(c1 is c2))

Выход:

Id of c1 : 139699882512960
Id of c2 : 139699882512960
c1 is c2 ? True

Если мы сделаем так, как показано ниже, мы получим TypeError:

try:
    p = DBConnection()
except TypeError as ex:
    print("ERROR: {}".format(ex.message))

Надеюсь, эта статья поможет вам реализовать шаблон singleton в любом классе.