Что такое паттерны в python

Шаблоны Python Design — Краткое руководство

Шаблоны проектирования используются для представления шаблона, используемого разработчиками для создания программного обеспечения или веб-приложения. Эти шаблоны выбираются на основе анализа требований. Шаблоны описывают решение проблемы, когда и где применять решение и последствия реализации.

Структура шаблона дизайна

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

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

Имя образца

Он описывает шаблон в краткой и эффективной манере.

Намерение / Motive

Он описывает, что делает шаблон.

применимость

Он описывает список ситуаций, в которых применяется шаблон.

Участники и последствия

Участники включают в себя классы и объекты, которые участвуют в шаблоне проектирования со списком последствий, которые существуют в шаблоне.

Почему питон?

Python — это язык сценариев с открытым исходным кодом. Он имеет библиотеки, которые поддерживают различные шаблоны проектирования. Синтаксис python прост для понимания и использует английские ключевые слова.

Python обеспечивает поддержку списка шаблонов проектирования, которые упомянуты ниже. Эти шаблоны проектирования будут использоваться в этом уроке —

Преимущества использования шаблона проектирования

Ниже приведены различные преимущества шаблона проектирования —

Шаблоны предоставляют разработчику выбор проверенных и проверенных решений для указанных проблем.

Все шаблоны дизайна не зависят от языка.

Шаблоны помогают добиться коммуникации и хорошо документировать документацию.

Он включает в себя отчет о достижениях для снижения любого технического риска для проекта.

Шаблоны проектирования очень гибки в использовании и просты для понимания.

Шаблоны предоставляют разработчику выбор проверенных и проверенных решений для указанных проблем.

Все шаблоны дизайна не зависят от языка.

Шаблоны помогают добиться коммуникации и хорошо документировать документацию.

Он включает в себя отчет о достижениях для снижения любого технического риска для проекта.

Шаблоны проектирования очень гибки в использовании и просты для понимания.

Python Design Patterns — Gist

Python — это язык сценариев с открытым исходным кодом, который является высокоуровневым, интерпретируемым, интерактивным и объектно-ориентированным. Это разработано, чтобы быть очень удобочитаемым. Синтаксис языка Python прост для понимания и часто использует английские ключевые слова.

Особенности языка Python

В этом разделе мы узнаем о различных особенностях языка Python.

Интерпретированный

Python обрабатывается во время выполнения с использованием интерпретатора. Нет необходимости компилировать программу перед выполнением. Это похоже на PERL и PHP.

Объектно-ориентированный

Python следует объектно-ориентированному стилю и шаблонам дизайна. Он включает в себя определение класса с различными функциями, такими как инкапсуляция, полиморфизм и многое другое.

портативный

Код Python написан в операционной системе Windows и может использоваться в операционной системе Mac. Код можно использовать повторно и переносить в соответствии с требованиями.

Легко кодировать

Синтаксис Python легко понять и кодировать. Любой разработчик может понять синтаксис Python в течение нескольких часов. Python может быть описан как «дружественный к программисту»

растяжимый

При необходимости пользователь может написать часть кода Python на языке Си. Также возможно поместить код Python в исходный код на разных языках, таких как C ++. Это делает Python расширяемым языком.

Важные моменты

Рассмотрим следующие важные моменты, связанные с языком программирования Python —

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

Его можно использовать как язык сценариев или как язык программирования.

Включает в себя автоматическую сборку мусора.

Он включает в себя динамические типы данных высокого уровня и поддерживает различные проверки динамических типов.

Python включает в себя функцию интеграции с C, C ++ и такими языками, как Java.

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

Его можно использовать как язык сценариев или как язык программирования.

Включает в себя автоматическую сборку мусора.

Он включает в себя динамические типы данных высокого уровня и поддерживает различные проверки динамических типов.

Python включает в себя функцию интеграции с C, C ++ и такими языками, как Java.

Как скачать язык Python в вашей системе?

Чтобы скачать язык Python в вашей системе, перейдите по этой ссылке —

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

Он включает в себя пакеты для различных операционных систем, таких как дистрибутивы Windows, MacOS и Linux.

Важные инструменты в Python

В этом разделе мы кратко узнаем о нескольких важных инструментах в Python.

Python Strings

Основное объявление строк выглядит следующим образом:

Списки Python

Списки Python могут быть объявлены как составные типы данных, разделенные запятыми и заключенные в квадратные скобки ([]).

Python Tuples

Кортеж — это динамический тип данных Python, который состоит из числа значений, разделенных запятыми. Кортежи заключены в круглые скобки.

Словарь Python

Словарь Python — это тип хэш-таблицы. Ключом словаря может быть практически любой тип данных Python. Типы данных обычно представляют собой числа или строки.

Что представляет собой шаблон дизайна в Python?

Python помогает создать шаблон проектирования, используя следующие параметры:

Модель контроллера представления модели

Model View Controller — наиболее часто используемый шаблон проектирования. Разработчикам легко реализовать этот шаблон проектирования.

Ниже приведена базовая архитектура контроллера представления модели:

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

Давайте теперь посмотрим, как работает структура.

модель

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

Посмотреть

Представление представляет файлы HTML, которые взаимодействуют с конечным пользователем. Он представляет данные модели для пользователя.

контроллер

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

Код Python

Давайте рассмотрим базовый объект «Человек» и создадим шаблон проектирования MVC.

Он вызывает метод, который выбирает все записи таблицы Person в базе данных. Записи представлены в формате JSON.

Посмотреть

Он отображает все записи, извлеченные в модели. Представление никогда не взаимодействует с моделью; Контроллер выполняет эту работу (общение с моделью и представлением).

контроллер

Контроллер взаимодействует с моделью через метод getAll (), который выбирает все записи, отображаемые для конечного пользователя.

Шаблоны дизайна Python — Singleton

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

Он обеспечивает глобальную точку доступа к созданному экземпляру.

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

Как реализовать одноэлементный класс?

Следующая программа демонстрирует реализацию одноэлементного класса, где она печатает экземпляры, созданные несколько раз.

Выход

Вышеуказанная программа генерирует следующий вывод —

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

Количество созданных экземпляров одинаково, и нет различий в объектах, перечисленных в выходных данных.

Python Design Patterns — Factory

Заводской шаблон относится к категории списка шаблонов. Он предоставляет один из лучших способов создания объекта. В фабричном шаблоне объекты создаются без предоставления логики клиенту и обращения к вновь созданному объекту с использованием общего интерфейса.

Фабричные шаблоны реализованы в Python с использованием фабричного метода. Когда пользователь вызывает метод, такой, что мы передаем строку, а возвращаемое значение в качестве нового объекта реализуется через фабричный метод. Тип объекта, используемого в фабричном методе, определяется строкой, которая передается через метод.

В приведенном ниже примере каждый метод включает объект в качестве параметра, который реализуется через фабричный метод.

Как реализовать фабричный шаблон?

Давайте теперь посмотрим, как реализовать фабричный шаблон.

Класс кнопки помогает создавать HTML-теги и связанную HTML-страницу. Клиент не будет иметь доступа к логике кода, а выходные данные представляют собой создание html-страницы.

Выход

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

объяснение

Код Python включает в себя логику тегов html, в которой указано значение. Конечный пользователь может посмотреть файл HTML, созданный кодом Python.

Python Design Patterns — Builder

Builder Pattern — это уникальный шаблон проектирования, который помогает строить сложные объекты с использованием простых объектов и использует алгоритмический подход. Этот шаблон дизайна относится к категории шаблонов творчества. В этом шаблоне проектирования класс построителя создает конечный объект в пошаговой процедуре. Этот строитель не зависит от других объектов.

Преимущества Builder Pattern

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

Это обеспечивает лучший контроль над процессом построения созданного шаблона.

Это дает идеальный сценарий для изменения внутреннего представления объектов.

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

Это обеспечивает лучший контроль над процессом построения созданного шаблона.

Это дает идеальный сценарий для изменения внутреннего представления объектов.

Как реализовать шаблон строителя?

В этом разделе мы узнаем, как реализовать шаблон компоновщика.

Выход

Вышеуказанная программа генерирует следующий вывод —

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

Шаблоны дизайна Python — прототип

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

Вновь скопированный объект может иметь некоторые изменения в свойствах, если это необходимо. Такой подход экономит время и ресурсы, необходимые для разработки продукта.

Как реализовать шаблон прототипа?

Давайте теперь посмотрим, как реализовать шаблон прототипа.

Выход

Вышеуказанная программа сгенерирует следующий вывод —

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

Вывод помогает в создании новых объектов с существующими, и это ясно видно в выводе, упомянутом выше.

Шаблоны дизайна Python — Фасад

Шаблон проектирования фасада предоставляет унифицированный интерфейс для набора интерфейсов в подсистеме. Он определяет интерфейс более высокого уровня, который может использовать любая подсистема.

Фасадный класс знает, какая подсистема отвечает за запрос.

Как оформить фасадный рисунок?

Давайте теперь посмотрим, как спроектировать рисунок фасада.

Выход

Вышеуказанная программа генерирует следующий вывод —

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

объяснение

Эта программа разработана со сценарием. Это запуск двигателя автомобиля или любого транспортного средства. Если вы соблюдаете код, он включает в себя соответствующие функции для вождения, парковки и потребления топлива.

Шаблоны проектирования Python — Команда

Командный шаблон добавляет уровень абстракции между действиями и включает в себя объект, который вызывает эти действия.

В этом шаблоне проектирования клиент создает объект команды, который включает в себя список команд, которые должны быть выполнены. Созданный объект команды реализует определенный интерфейс.

Ниже приводится базовая архитектура шаблона команды —

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

Как реализовать шаблон команды?

Теперь мы увидим, как реализовать шаблон проектирования.

Выход

Вышеуказанная программа генерирует следующий вывод —

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

объяснение

Вывод реализует все команды и ключевые слова, перечисленные на языке Python. Он печатает необходимые значения переменных.

Шаблоны проектирования Python — Адаптер

Шаблон адаптера работает как мост между двумя несовместимыми интерфейсами. Этот тип шаблона проектирования подпадает под структурный шаблон, поскольку этот шаблон сочетает в себе возможности двух независимых интерфейсов.

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

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

Источник

Pattern matching. Теперь и в Python

В юбилейный минор третьего питона наконец-то завезли pattern matching. Саму концепцию сложно назвать новой, она уже реализована во многих языках, причём как нового поколения (Rust, Golang), так и у тех, кому уже за 0x18 (Java).

Анонсировал pattern matching Гвидо ван Россум, автор языка программирования Python и «великодушный пожизненный диктатор»

Меня зовут Денис Кайшев, я код-ревьюер на курсе «Мидл Python-разработчик». В этом посте хочу рассказать, зачем в Python pattern matching и как с ним работать.

Синтаксически конструкция pattern matching по сути аналогична тому, как это представлено в ряде других языков:

Может показаться сложным и запутанным, но на самом деле всё сводится примерно к такому виду:

Это выглядит куда понятнее и приятнее глазу.

Сами шаблоны разбиты на несколько групп:

Literal Patterns

Паттерн Literal, как намекает нам название, предполагает сопоставление между собой ряда значений, а именно строк, чисел, булевых значений и NULLNone.

Capture Patterns

Шаблон захвата позволяет связать переменную с заданным в шаблоне именем и использовать это имя внутри локальной области видимости.

Wildcard Pattern

Constant Value Patterns

При использовании констант нужно использовать dotted names, к примеру перечисления, иначе сработает паттерн захвата.

И ожидаемый результат будет не самым очевидным.

Sequence Patterns

Mapping Patterns

И всё бы ничего, но есть особенность. Этот паттерн гарантирует вхождение этого ключа (ключей) в словарь, но длина словаря не имеет значения. Поэтому на экране появится i find positional args and one keyword args.

Class patterns

Что касается пользовательских типов данных, то здесь используется синтаксис, схожий с инициализацией объекта.

Вот как это будет выглядеть на примере дата-классов:

Иначе вызовется исключение TypeError: Coordinate() accepts 0 positional sub-patterns (3 given)

Что в итоге?

Армин Ронахер, создатель веб-фреймворка Flask для Python, очень ёмко описал текущее состояние Pattern matching

Да, сложно спорить: код станет несколько чище, нежели это была бы башня из if/else на треть экрана. Но и назвать это тем, что производит вау-эффект, тоже нельзя. Неплохо, что оно вводится: местами это будет удобно использовать, но не везде. Так или иначе, главное с этой новизной не переусердствовать, не бежать быстрее обновлять все проекты на 3.10 и всё переписывать, ведь:

Now is better than never. Although never is often better than right now.

Источник

Шаблоны проектирования в Python

Перевод статьи Design Patterns in Python Вступление Шаблоны проектирования – это многоразовые модели для решения известных и распространенных проблем в…

Что такое паттерны в python. Смотреть фото Что такое паттерны в python. Смотреть картинку Что такое паттерны в python. Картинка про Что такое паттерны в python. Фото Что такое паттерны в python

Вступление

Шаблоны проектирования – это многоразовые модели для решения известных и распространенных проблем в архитектуре программного обеспечения.

Они лучше всего описываются как шаблоны для работы с определенной обычной ситуацией. Архитектор может иметь шаблон для проектирования определенных видов дверных рам, который он вписывает во многие свои проекты, а инженер-программист или архитектор программного обеспечения должен знать шаблоны для решения частых задач программирования.

Хорошая презентация шаблона проектирования должна включать в себя:

Эквивалентные Проблемы

Если бы вы думали, что это довольно расплывчатое понятие, Вы были бы правы. Например, мы могли бы сказать, что следующий “паттерн” решает все ваши проблемы:

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

С другой стороны, вы можете иметь решения, которые слишком конкретны, чтобы их можно было назвать шаблоном. Например, вы можете задаться вопросом, Является ли QuickSort шаблоном для решения проблемы сортировки.

Это, безусловно, распространенная проблема программирования, и QuickSort – хорошее решение для нее. Однако он может быть применен к любой проблеме сортировки практически без изменений.

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

Эквивалентные проблемы находятся где-то между этими понятиями. Это разные проблемы, которые достаточно похожи, чтобы вы могли применить к ним одну и ту же модель, но достаточно разные, чтобы эта модель была значительно настроена, чтобы быть применимой в каждом конкретном случае.

Паттерны, которые могут быть применены к такого рода проблемам, – это то, что мы можем осмысленно назвать паттернами проектирования.

Зачем использовать шаблоны проектирования?

Вы, вероятно, знакомы с некоторыми шаблонами проектирования уже через практику написания кода. Многие хорошие программисты в конечном итоге тяготеют к ним, даже не будучи явно обученными, или они просто берут их у старших по пути.

Мотивация для создания, изучения и использования шаблонов проектирования имеет много значений. Это способ дать названия сложным абстрактным понятиям, чтобы обеспечить обсуждение и обучение.

Они делают общение внутри команды быстрее, потому что кто-то может просто использовать имя шаблона вместо того, чтобы вызывать доску. Они позволяют вам учиться на опыте людей, которые были до вас, а не изобретать велосипед, проходя через весь тигель постепенно улучшающихся практик самостоятельно (и постоянно съеживаясь от своего старого кода).

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

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

Шаблоны проектирования в Python

Традиционно модели проектирования были разделены на три основные категории: креативные, структурные и поведенческие. Есть и другие категории, такие как архитектурные шаблоны или шаблоны параллелизма, но они выходят за рамки этой статьи.

Существуют также специфические для Python шаблоны проектирования, которые создаются специально вокруг проблем, которые предоставляет сама структура языка, или которые решают проблемы специальными способами, которые разрешены только из-за структуры языка.

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

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

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

Источник

Порождающие шаблоны в Python

Первая статья в небольшой серии статей, посвященных шаблонам проектирования в Python.

Порождающие шаблоны

Порождающие шаблоны, как следует из названия, имеют дело с созданием классов или объектов.

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

Они очень полезны для понижения уровня зависимости между классами и управления взаимодействием пользователя с ними.

Шаблоны, описанные в этой статье:

Factory

Проблема

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

Тем не менее, клиент решает расширить свой бизнес и теперь будет предоставлять свои услуги и безработным, хотя и с другими процедурами и условиями.

Теперь вам нужно создать совершенно новый класс для безработных, который возьмет совершенно другого конструктора! Но теперь вы не знаете, какой конструктор вызывать в общем случае, тем более, какие аргументы ему нужно передать.

Вы можете использовать некоторые уродливые условия во всем коде, где каждый вызов конструктора будет окружен операторами if, и вы вынуждены будете используете какую-то дорогостоящую операцию для проверки типа самого объекта.

Если во время инициализации будут возникать ошибки, вы будете тратить время на их поиск, и редактирования кода, в каждом из ста мест, в которых используются конструкторы.

Понятно что такой подход менее чем желателен, он не масштабируется и вообще неустойчив.

В качестве альтернативы, вы можете рассмотреть фабричный шаблон.

Решение

Фабрики используются для инкапсуляции информации о классах, и при этом для создания их экземпляров на основе определенных параметров, которые им предоставляются.

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

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

Если мы просто получим другую фабрику в качестве параметра, нам даже не нужно будет знать, какой класс она производит. Нам просто нужен метод единой фабрики, который возвращает класс с гарантированным набором поведений. Давайте создадим фабрику.

Для начала не забудьте включить абстрактные методы:

Нам нужны созданные ранее классы для реализации некоторого набора методов, которые позволяют работать с ними единообразно. Для этого мы реализуем следующий интерфейс:

И теперь мы наследуем от него Worker и Unemployed:

Теперь, когда у нас есть наши работники, давайте сделаем для них фабрику:

Здесь для ясности мы жестко закодировали параметры, хотя обычно вы просто создаете экземпляр класса и заставляете его делать свое дело.

Чтобы проверить, как все это работает, давайте создадим экземпляр нашей фабрики и позволим ей произвести пару работников:

Abstract Factory

Проблема

Вам нужно создать семейство разных предметов. Хотя они разные, они так или иначе сгруппированы по определенной характеристике.

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

Решение

Идея очень похожа на обычный шаблон фабрики, единственное отличие состоит в том, что все фабрики имеют несколько отдельных методов для создания объектов, и тип фабрики определяет семейство объектов.

Абстрактная фабрика отвечает за создание целых групп объектов, наряду с их соответствующими фабриками, — но она не касается конкретных реализаций этих объектов. Эта часть оставлена для их соответствующих фабрик:

Мы можем проверить результаты, создав фабрики и вызвав соответствующие методы cook() для всех объектов:

Builder

Проблема

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

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

А теперь представьте себе какой может быть конструктор для такого объекта:

Создание этого класса было бы крайне нечитаемым, было бы очень легко ошибиться в некоторых типах аргументов, так как мы работаем в Python, и можем накапливать бесчисленное количество аргументов в конструкторе.

Кроме того, что если мы не хотим, чтобы робот реализовал все поля в классе? Что если мы хотим, чтобы у него были только ноги, а не ноги и колеса?

Python не поддерживает перегруженные конструкторы, которые помогли бы нам определить такие случаи (и даже если бы мы могли, это привело бы только к еще более грязным конструкторам).

Решение

Мы можем создать класс Builder, который создает наш объект и добавляет соответствующие модули нашему роботу. Вместо замысловатого конструктора мы можем создать экземпляр объекта и добавить необходимые компоненты с помощью функций.

Мы вызываем конструкцию каждого модуля отдельно, после создания объекта. Давайте продолжим и определим класс Robot с некоторыми значениями по умолчанию:

Обратите внимание, что мы пропустили определенные инициализации в конструкторе и использовали вместо них значения по умолчанию. Это потому, что мы будем использовать классы Builder для инициализации этих значений.

Сначала мы реализуем абстрактный Builder, который определяет наш интерфейс для сборки:

Теперь мы можем реализовать несколько видов Builders, которые подчиняются этому интерфейсу, например, для Android и для автономного автомобиля:

Заметьте, как они реализуют одни и те же методы, но под ними по-разному строится структура объектов, и конечному пользователю не нужно разбираться в деталях этой структуры?

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

Давайте попробуем использовать AndroidBuilder для создания андроидного робота:

Запуск этого кода даст:

А теперь давайте воспользуемся AutonomousCarBuilder для сборки автомобиля:

Запуск этого кода даст:

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

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

Запуск этого кода выдаст:

Тем не менее, шаблон Builder не имеет большого смысла для небольших, простых классов, поскольку добавленная логика для их построения просто добавляет сложности.

Хотя, когда дело доходит до больших, сложных классов с многочисленными областями, такими как многослойные нейронные сети — паттерн Builder спасает жизнь.

Prototype

Проблема

Допустим нам нужно клонировать объект, но мы можем не знать его точный тип и его параметры. Все они могут быть назначены не в конструкторе или могут зависеть от состояния системы в конкретной точке во время выполнения.

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

Решение

Шаблон проектирования Prototype решает проблему копирования объектов путем делегирования этой задачи самим объектам. Все объекты, которые можно копировать, должны реализовать метод clone и использовать его для получения точных копий самих себя.

Давайте продолжим и определим общую функцию clone для всех дочерних классов, а затем унаследуем ее от родительского класса:

В качестве альтернативы вы можете использовать функцию deepcopy вместо простого назначения полей, как в предыдущем примере:

Шаблон Prototype может быть действительно полезен в крупномасштабных приложениях, которые создают множество объектов. Иногда копирование уже существующего объекта обходится дешевле, чем создание нового.

Singleton

Проблема

Singleton — это объект с двумя основными характеристиками:

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

Наличие только одного экземпляра обычно является механизмом управления доступом к некоторому общему ресурсу. Например, два потока могут работать с одним и тем же файлом, поэтому вместо того, чтобы открывать его по отдельности, Singleton может предоставить им уникальную точку доступа.

Глобальная доступность важна, потому что после того, как ваш класс был создан один раз, вам нужно будет передать этот единственный экземпляр для работы с ним. И не всегда такое возможно будет повторить. Вот почему легче убедиться, что всякий раз, когда вы снова пытаетесь создать экземпляр класса, вы просто получаете тот же экземпляр, который у вас уже был.

Решение

Давайте реализуем шаблон Singleton, сделав объект глобально доступным и ограниченным одним экземпляром:

Тип данных Optional, может содержать либо класс, указанный в [], либо None.

Определение метода __call__ позволяет использовать экземпляры класса в качестве функций. Метод также вызывается во время инициализации, поэтому, когда мы вызываем что-то вроде a = Singleton(), вызывается метод __call__ своего базового класса.

В Python все является объектом. Все обычные классы, которые вы пишете, а также стандартные классы, имеют type в качестве типа объекта. Даже type относится к type.

Это означает, что type является метаклассом — другие классы являются экземплярами type, точно так же, как переменные объекты являются экземплярами этих классов. В нашем случае Singleton является экземпляром MetaSingleton.

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

super(MetaSingleton, cls).__call__(* args, ** kwargs) вызывает суперкласс __call__. Наш суперкласс в этом случае — это type, имеющий реализацию __call__, которая будет выполнять инициализацию с заданными аргументами.

Мы указали type(MetaSingleton), значение, которое будет присвоено полю _instance (cls).

Целью использования метакласса в этом случае, а не использрвание более простой реализацией, по сути, является возможность повторного использования кода.

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

Теперь мы можем попробовать использовать его:

Из-за своей глобальности целесообразно интегрировать обеспечение безопасности потоков в Singleton. К счастью, нам не нужно слишком много редактировать, чтобы сделать это. Мы можем просто немного отредактировать MetaSingleton:

Таким образом, если два потока начнут создавать экземпляр Singleton одновременно, один остановится на блокировке. Когда менеджер контекста снимает блокировку, другой вводит оператор if и видит, что экземпляр действительно уже был создан другим потоком.

Object Pool

Проблема

Допустим у нас есть класс в нашем проекте, который называется MyClass. MyClass очень полезен для нас и мы его часто используем на протяжении всего проекта, хотя и в течение коротких периодов времени.

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

Решение

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

Если объект имеет какое-то начальное состояние по умолчанию, освобождение всегда будет перезапускать его.

Реализуем пример ObjectPool и сначала определим MyClass:

И чтобы проверить это:

Обратите внимание, что это простейшая реализация, и на практике этот шаблон может использоваться вместе с Singleton для обеспечения единого пула, доступного в глобальном масштабе.

Обратите внимание, что полезность этого шаблона обсуждается в языках, которые используют сборщик мусора. Распределение объектов, которые занимают только память (то есть никаких внешних ресурсов), как правило, является относительно недорогим в таких языках, в то время как много «живых» ссылок на объекты могут замедлить сборку мусора, потому что GC нужно проходить через все ссылки.

Заключение

Мы рассмотрели наиболее важные порождающие шаблоны проектирования в Python — проблемы, которые они решают, и способы их решения.

Знание шаблонов проектирования — чрезвычайно удобный набор навыков для всех разработчиков, поскольку они предоставляют решения общих проблем, возникающих в программировании.

Зная о мотивах и решениях, вы также можете избежать случайного появления анти-паттерна при попытке решить проблему.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *