Как реализовать инверсию зависимостей и разделение интерфейсов для конкретного класса, который необходимо инициировать?Python

Программы на Python
Гость
Как реализовать инверсию зависимостей и разделение интерфейсов для конкретного класса, который необходимо инициировать?

Сообщение Гость »

Контекст

Насколько я понимаю, принципы инверсии зависимостей и разделения интерфейсов SOLID OOP предписывают нам писать нашу программу в соответствии с интерфейсом, а не внутренние детали. Итак, я пытаюсь разработать простой сборщик данных фондового рынка на Python, примерно со следующей объектной диаграммой, где main инкапсулирует бизнес-логику приложения, обработку пользовательского ввода и т. д. Вот как это понять< /p>
  • Розовый цвет представляет конкретную функцию или класс, зеленый — абстрактный класс.
  • Полый наконечник стрелки представляет подкласс отношений/реализует. , а сплошная стрелка обозначает связь использование (в соответствии с соглашением Чистая архитектура Роберта Мартина)
Изображение

Итак, основное Функция использует абстрактный интерфейс, который извлекает цену акции по символу. Абстрактный класс выглядит так:

Код: Выделить всё

#!/usr/bin/env python3
# encoding: utf-8

"""
Defines the abstract stock price reader
"""
from abc import ABC, abstractmethod
class StockPriceReader(ABC):
"""Defines the general tick reader interface."""
@abstractmethod
def get_price(self, symbol:str)->float:
"""
Gets the price of a stock represented by the symbol, e.g
when symbol='AAPL', it gets the Apple Inc stock price.
"""
raise NotImplementedError

Класс TickReaderConcrete реализует внутренние детали и получает фактическую цену акций с помощью чего-то вроде вызова API Bloomberg или торговой биржи. Учетные данные, необходимые для вызова API, должны быть частью внутренних данных. Код здесь не показан, так как его довольно просто реализовать.

Дилемма

Теперь, основываясь на приведенной выше простой диаграмме зависимостей классов, то же самое книга (Чистая архитектура), похоже, подразумевает это (здесь я подчеркиваю)

Основной блок должен даже не знать что TickReaderConcrete существует.

По крайней мере, я так понимаю, о чем говорит книга, поскольку на главной странице нет стрелки в TickReaderConcrete, поправьте меня, если я ошибаюсь.
Но когда я пишу main.py, я не могу притворяться, что TickReaderConcrete > существует, другими словами, кажется основным не может не знать о существовании TickReaderConcrete, когда код выглядит так:

Код: Выделить всё

#!/usr/bin/env python3
# encoding: utf-8

"""
The main function to invoke the stockprice reader
"""
from tickreader import TickReaderConcrete
...
if __name__ == '__main__':
# This line gives rise to the alternative class diagram below
reader=TickReaderConcrete(...)

# After initialised, we can use the interface permitted by the abstract base class
reader.get_price(symbol='IBM')
Вопрос
Так как же сделать так, чтобы основной не знал о существовании конкретного читателя? Если main вообще не импортирует конкретный объект чтения, он не может даже создать экземпляр конкретного объекта чтения, а абстрактный модуль чтения все равно не может быть инициализирован.
Итак, как в принципе организовать код для правильной реализации объектной диаграммы выше?
Слегка перефразированный вопрос
Даже если абстрактный базовый класс предоставляет необходимые общедоступные методы, по крайней мере, инициализацию< /em> требует знания о существовании конкретного подкласса. Может ли конкретный подкласс спрятаться за абстрактным базовым классом? Посмотрите на альтернативную объектную диаграмму, которая реализована в приведенном выше фрагменте кода. Как избавиться от ломаной линии?
Изображение


Подробнее здесь: https://stackoverflow.com/questions/781 ... concrete-c

Вернуться в «Python»