Это инъекция зависимостей и / или шаблон Singleton? - PullRequest
2 голосов
/ 05 мая 2020

TL; DR: В чем разница между внедрением зависимостей и шаблоном синглтона, если внедренный объект является синглтоном? *

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

Я решил решить эту проблему с помощью Singleton:

class ConfigMeta(type):
    _instance = None

    def __call__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__call__(*args, **kwargs)
        return cls._instance


class Config(metaclass=ConfigMeta):

    def __init__(self) -> None:
        pass

Но поиск показал, что это подвержено ошибкам и считается плохой практикой (при управлении состояниями классов). Почти в каждом посте предлагается использовать внедрение зависимостей, но они сбивают меня с толку тем, как они это делают. Все они заявляют: «Ваша реализация может быть синглтоном, но вставлять ее в другие объекты в их конструкторах».

Это будет что-то вроде:

# foo.py

from config import Config

class Foo:

    def __init__(self):
        self.config = Config()

# bar.py

from config import Config

class Bar:

    def __init__(self):
        self.config = Config()

Однако каждый из них self.config относится к одному и тому же экземпляру. Отсюда моя путаница ...

Как это считается инъекцией зависимостей, а не шаблоном Singleton?

Если это считается инъекцией зависимостей, как это будет выглядеть как просто Singleton Шаблон?

Ответы [ 2 ]

1 голос
/ 05 мая 2020

При внедрении зависимостей (DI) вы предоставляете системе DI решать, как получить конкретный объект c. Вы просто объявляете, какой объект вам нужен. Это дополняет шаблон Singleton, в котором все приложение обслуживается одним экземпляром определенного типа c. Так, например:

class Config:
    pass

config = Config()  # singleton

class Foo:
    def __init__(self):
        config = config

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

С другой стороны, при внедрении зависимостей есть центральный блок для обработки подобных вещей. Класс пользователя просто объявляет, какой объект ему требуется. Например:

class DI:
    config = Config()

    @classmethod
    def get_config_singleton(cls):
        return cls.config

    @classmethod
    def get_config(cls):
        return Config()

    @classmethod
    def inject(cls, func):
        from functools import partialmethod
        # The DI system chooses what to use here:
        return partialmethod(func, config=cls.get_config())


class Foo:
    @DI.inject  # it's up to the DI system to resolve the declared dependencies
    def __init__(self, config: Config):  # declare one dependency `config`
        self.config = config
0 голосов
/ 05 мая 2020

Внедрение зависимостей означает предоставление конструктору инициализированного объекта, в данном случае config.

Код в вашем вопросе не использует внедрение зависимостей, поскольку конструктор __init__ не получает config в качестве аргумента, поэтому здесь используется только шаблон singleton.

См. Дополнительную информацию здесь о внедрении зависимостей в Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...