Зарегистрируйтесь, чтобы продолжить обучение

Декоратор (Паттерн) Python: Полиморфизм

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

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

В этом уроке мы разберем, как реализовать паттерн «Декоратор» и поговорим о преимуществах и недостатках использования декораторов.

Как реализовать паттерн «Декоратор»

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

В Python паттерн «Декоратор» можно легко реализовать с помощью встроенной функциональности декораторов. Но сначала мы рассмотрим его реализацию в более общем ООП стиле для лучшего понимания. Разберем применение этого паттерна по шагам.

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

  1. Создадим базовый класс Comment, который будет содержать текст комментария и метод display, отображающий этот текст:
class Comment:
    def __init__(self, text):
        self.text = text

    def display(self):
        return self.text

Класс Comment является базовым и представляет собой комментарий с текстом и методом display для его отображения. Этот класс служит основой для нашего декоратора.

Теперь, чтобы добавить функциональность фильтрации нежелательных слов, мы могли бы изменить класс Comment. Но это нарушило бы принцип открытости-закрытости SOLID. Вместо этого мы можем использовать паттерн «Декоратор».

  1. Создадим декоратор ProfanityFilterDecorator, который будет фильтровать нежелательные слова:
class ProfanityFilterDecorator:
    def __init__(self, comment):
        self.comment = comment
        self.profanities = {"badword1", "badword2"}

    def display(self):
        words = self.comment.display().split()
        result_words = [
            word if word not in self.profanities else "***" for word in words
        ]
        return " ".join(result_words)

В этом примере класс ProfanityFilterDecorator оборачивает объект Comment и переопределяет метод display так, чтобы фильтровать определенные нежелательные слова в тексте комментария. Исходный объект Comment остается неизменным, а декоратор добавляет новое поведение — фильтрацию нежелательных слов.

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

  1. Создадим комментарий и применим к нему декоратор для фильтрации нежелательных слов:
comment = Comment("This is a comment with a badword1")
print(comment.display())  # => "This is a comment with a badword1"

comment = ProfanityFilterDecorator(comment)
print(comment.display())  # => "This is a comment with a ***"

Здесь мы видим пример использования полиморфизма: объект ProfanityFilterDecorator ведет себя как объект Comment, но добавляет новое поведение — фильтрацию нежелательных слов.

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

Выводы

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

Для полного доступа к курсу нужен базовый план

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

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

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

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff