Рубрики
Без рубрики

Реализация типов просмотра в Python

Узор для реализации типов просмотра, которые действительно скрывают детали реализации в Python. Помечено с Python, кодированием, программированием, шаблонами.

На объектно-ориентированных языках, таких как 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”