🎉 Ура! После трёх лет работы, я наконец выпустил английскую версию книги о паттернах! Вот она »
Одиночка

Одиночка на Python

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

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

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

Подробней об Одиночке

Особенности паттерна на Python

Сложность:

Популярность:

Применимость: Многие программисты считают Одиночку антипаттерном, поэтому его всё реже и реже можно встретить в Python-коде.

Признаки применения паттерна: Одиночку можно определить по статическому создающему методу, который возвращает один и тот же объект.

Наивный Одиночка (один поток)

Топорно реализовать Одиночку очень просто — достаточно скрыть конструктор и предоставить статический создающий метод.

Тот же класс ведёт себя неправильно в многопоточной среде. Несколько потоков могут одновременно вызвать метод получения Одиночки и создать сразу несколько экземпляров объекта.

main.py: Conceptual Example

from __future__ import annotations
from typing import Optional


class Singleton:
    """
    Класс Одиночка предоставляет метод getInstance, который позволяет
    клиентам получить доступ к уникальному экземпляру одиночки.
    """

    _instance: Optional<a href="/ru/design-patterns/singleton">Одиночка</a> = None

    def __init__(self) -> None:
        if Singleton._instance is not None:
            raise ReferenceError("Cannot instantiate a singleton class.")
        else:
            Singleton._instance = self

    @staticmethod
    def get_instance() -> Singleton:
        """
        Статический метод, управляющий доступом к экземпляру одиночки.
        
        Эта реализация позволяет вам расширять класс Одиночки, сохраняя
        повсюду только один экземпляр каждого подкласса.
        """

        if not Singleton._instance:
            Singleton()
        return Singleton._instance

    def some_business_logic(self):
        """
        Наконец, любой одиночка должен содержать некоторую бизнес-логику,
        которая может быть выполнена на его экземпляре.
        """

        # ...


if __name__ == "__main__":
    # Клиентский код.

    s1 = Singleton.get_instance()
    s2 = Singleton.get_instance()

    if id(s1) == id(s2):
        print("Singleton works, both variables contain the same instance.")
    else:
        print("Singleton failed, variables contain different instances.")

Output.txt: Output

Singleton works, both variables contain the same instance.

Одиночка in Other Languages

Одиночка in Java Одиночка in C# Одиночка in PHP Одиночка in TypeScript