На объектно-ориентированных языках, таких как Java, C # или Kotlin, учитывая тип T
ассоциированный Просмотр типа TView
используется для выставления определенного вида (части) объекта типа T
. Это помогает скрыть детали реализации.
Например, в следующем Котлин Пример, Леджера
Интерфейс используется для обеспечения доступа к книге, скрывая основные детали реализации, то есть Ledgerimpl
Предоставляет функциональные возможности книги и у него есть процесс
и Контейнер
члены.
interface Ledger { fun getValue(i: Int): Int? } class LedgerImpl: Ledger { val container = HashMap() override fun getValue(i: Int) = container.get(i) fun process() { // processing } } fun getLedger(): Ledger { val c = LedgerImpl() c.process() return c as Ledger }
Да, мы можем имитировать вышеуказанную структуру кода в Python следующим образом.
from abc import ABC from collections import defaultdictclass Ledger(ABC): def get_value(self, i: int) -> int: passclass _LedgerImpl(Ledger): def __init__(self): self._container = defaultdict(int) def get_value(self, i: int) -> int: return self._container[i] def process(self) -> None: ... def facade() -> Ledger: l = _LedgerImpl() l.process() return l
В то время как _Container
отмечается как частная конвенция (то есть имя префиксировано с подчеркиванием), абоненты Фасад
может еще получить доступ _Container
В возвращенном значении, так как Python не обеспечивает применение ограничений доступа во время выполнения. Итак, детали реализации не являются искренней.
(Случайно) Да, мы можем сделать лучше. Мы можем использовать NamedTuple
Поддержка в Python, чтобы реализовать тип просмотра.
from abc import ABC from collections import defaultdict from typing import Callable, NamedTuple class Ledger(NamedTuple): get_value: Callable[[int], int] class _LedgerImpl(): def __init__(self): self._container = defaultdict(int) def process(self) -> None: ... def get_view(self) -> Ledger: return Ledger(lambda x: self._container[x]) def facade() -> Ledger: l = _LedgerImpl() l.process() return l.get_view()
С этой реализацией, если мы не поправляем наш путь через лямбда, созданные в get_view.
Детали реализации остаются действительно скрыты по сравнению с предыдущей реализацией Python.
Также эта модель реализации опирается на композицию вместо наследства. Хотя более ранняя структура реализации может быть изменена для использования композиции, он все еще не по-настоящему скрывает детали реализации.
Этот шаблон идеально подходит для использования, когда детали реализации необходимо по-настоящему скрыть.
И вот мой критерий, когда следует по-настоящему скрыты детали реализации.
Если клиентские программы библиотеки/программы будут уважать ограничения доступа, переданные через конвенции, то этот шаблон не полезен/не требуется. Скорее всего, это если модули в библиотеке или программе выступают в качестве клиентов других модулей в библиотеке или программе. В этой ситуации более простые реализации видов зрения (например, первый пример питона) будет достаточно.
С другой стороны, если клиентские программы могут принимать зависимость от реализации библиотеки/программы (например, по причинам эффективности), когда текущая версия библиотеки/программы не поддерживает возможности, необходимые клиентскими программами, то этот шаблон может Будьте полезны, чтобы по-настоящему скрыть реализацию.
Я наткнулся на этот шаблон во время моих сессий кодирования. Поскольку я нашел его интересным и полезным, я провожу об этом. Тем не менее, как и во всех шаблонах, используйте их только тогда, когда они требуются.
(Изначально опубликовано здесь. )
Оригинал: “https://dev.to/rvprasad/implementing-view-types-in-python-5ba2”