При создании программных систем перед разработчиками часто встает проблема выбора тех или иных проектных решений. В этих случаях на помощь приходят паттерны. Дело в том, что почти наверняка подобные задачи уже решались ранее и уже существуют хорошо продуманные элегантные решения, составленные экспертами. Если эти решения описать и систематизировать в каталоги, то они станут доступными менее опытным разработчикам, которые после изучения смогут использовать их как шаблоны или образцы для решения задач подобного класса. Паттерны как раз описывают решения таких повторяющихся задач [6].
Сообразное использование паттернов проектирования дает разработчику ряд неоспоримых преимуществ. Приведем некоторые из них. Модель системы, построенная в терминах паттернов проектирования, фактически является структурированным выделением тех элементов и связей, которые значимы при решении поставленной задачи. Помимо этого, модель, построенная с использованием паттернов проектирования, более проста и наглядна в изучении, чем стандартная модель. Тем не менее, несмотря на простоту и наглядность, она позволяет глубоко и всесторонне проработать архитектуру разрабатываемой системы с использованием специального языка. Применение паттернов проектирования повышает устойчивость системы к изменению требований и упрощает неизбежную последующую доработку системы.
Существуют несколько типов паттернов проектирования, каждый из которых предназначен для решения своего круга задач:
Порождающие шаблоны — шаблоны проектирования, которые абстрагируют процесс инстанцирования. Они позволяют сделать систему независимой от способа создания, композиции и представления объектов. Шаблон, порождающий классы, использует наследование, чтобы изменять наследуемый класс, а шаблон, порождающий объекты, делегирует инстанцирование другому объекту. Существуют следующие порождающие шаблоны такие как: простая фабрика (Simple Factory), фабричный метод (Factory Method), абстрактная фабрика (Abstract Factory) и д.р.
Структурные шаблоны в основном связаны с композицией объектов, другими словами, с тем, как сущности могут использовать друг друга. Ещё одним объяснением было бы то, что они помогают ответить на вопрос «Как создать программный компонент?». Итак, структурные шаблоны — шаблоны проектирования, в которых рассматривается вопрос о том, как из классов и объектов образуются более крупные структуры. Примерами данного вида шаблонов являются адаптер (Adapter), мост (Bridge), компоновщик (Composite), декоратор (Decorator) и д.р.
Поведенческие шаблоны связаны с распределением обязанностей между объектами. Их отличие от структурных шаблонов заключается в том, что они не просто описывают структуру, но также описывают шаблоны для передачи сообщений / связи между ними. Или, другими словами, они помогают ответить на вопрос «Как запустить поведение в программном компоненте?». Поведенческие шаблоны — шаблоны проектирования, определяющие алгоритмы и способы реализации взаимодействия различных объектов и классов. К этому виду шаблонов относят цепочка обязанностей (Chain of Responsibility), команда (Command), итератор (Iterator), посредник (Mediator) и другие.
В Django реализован поведенческие паттерн Наблюдатель для организации сигналов, которые возникают, например, при добавлении записи в базу данных. Он создаёт механизм подписки, позволяющий одним объектам следить и реагировать на события, происходящие в других объектах.
Сигналы Django - это стратегия, позволяющая отделенным приложениям получать уведомления при наступлении определенных событий. Допустим, вы хотите аннулировать кэшированную страницу каждый раз, когда обновляется данный экземпляр модели, но в вашей базе кода есть несколько мест, где эту модель можно обновить. Вы можете сделать это, используя сигналы, перехватывая некоторые фрагменты кода, которые будут выполняться каждый раз, когда срабатывает метод сохранения этой конкретной модели. Другой распространенный случай - расширение пользовательского Django-пользователя с помощью стратегии профиля через отношение один-к-одному. Обычно мы используем «диспетчер сигналов» для прослушивания события post_save пользователя, чтобы также обновить экземпляр профиля.
На практике система сигналов разделяется на два компонента: sender — компонент посылающий сигнал; receiver — компонент отвечающий за обработку сигнала. Сам сигнал «испускается» в ORM Django (точнее за это отвечает Signal Dispatcher), наша задача только реализовать приемник (ни или обработчик сигнала) данного типа. Для этого в Django есть декоратор reciever(signal, **kwargs) рисунок 5.1.
Рисунок 5.1 - "Подписка" на сгенерированное событие
Сам наблюдатель реализуется в классе Signal(рисунок 5.2).
Рисунок 5.2 - Реализация наблюдателя
Мы видим, что при создании сигнала, есть список "подписчиков", которым сообщается, что данное событие произошло и его можно обрабатывать в пользовательских функциях рисунок 5.3.
Рисунок 5.3 - Реализация обработчика события
Дата | Выполнено, % |
---|---|
2020-05-19 19:37:36 | 10 |
2020-05-14 09:03:38 | 100 |