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

На этом занятии я покажу вам как можно реализовать паттерн «Моносостояние» для экземпляров классов в ООП Python. Вначале, что это такое и зачем нужно? Представьте, что у нас многопоточный процесс и каждый поток создает свой экземпляр определенного класса ThreadData. Нам бы хотелось, чтобы все они имели одинаковые локальные свойства и ссылались на одни и те же данные:

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

Реализовать это на Python очень просто. Объявим класс и в нем пропишем приватный словарь с некоторыми начальными свойствами, которыми будет обладать каждый экземпляр (или же этот словарь может быть пустым):

class ThreadData:
    __common_attrs = {
        'name': 'thread_1',
        'data': {},
        'id': 1,
    }
 
    def __init__(self):
        self.__dict__ = ThreadData.__common_attrs

Затем, в конструкторе этого класса, переопределим специальный словарь __dict__ на этот общий словарь класса __common_attrs. Таким образом, ссылка __dict__ в каждом экземпляре будет ссылаться на один и тот же словарь класса __common_attrs, а значит, иметь общие локальные свойства.

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

Давайте посмотрим, как это будет работать. Создадим экземпляр класса th1 = ThreadData:

th1 = ThreadData()

и в консоли Python можно видеть, что автоматически были созданы свойства экземпляра: name, data и id, как раз те, что прописаны в словаре __common_attrs.

Создадим второй экземпляр:

th2 = ThreadData()

Видим, что у него те же свойства по умолчанию. Давайте переопределим какое-либо из них и убедимся, что они действительно общие:

th2.id = 3

Смотрите, у обоих экземпляров свойство id стало равным 3. А если добавить новое свойство в экземпляр:

th1.attr_new = 'new attr'

то оно также появляется в обоих экземплярах. Вот так мы с вами реализовали паттерн «Моносостояние» на языке Python.