The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:
Шаблон декоратора является моим любимым среди всех остальных шаблонов, о которых я знаю. Он очень прост и в то же время очень мощный механизм, который делает ваш код высококогерентным и слабосвязанным. Однако, я считаю, что декораторы не используются достаточно часто. Они должны быть повсюду, но они этим не являются. Самое большое преимущество, которое мы получаем от декораторов, заключается в том, что они делают наш код композиционным. Вот почему название этого поста - композиционные декораторы. К сожалению, вместо декораторов мы часто используем императивные утилиты, которые делают наш код процедурным, а не объектно-ориентированным.
Во-первых, практический пример. Вот интерфейс для объекта, который должен где-то прочитать текст и вернуть его:
Вот реализация, которая считывает текст из файла:
А теперь декоратор, который является еще одной реализацией Text
и удаляет все непечатаемые символы из текста:
Вот как я это использую:
Как видите, PrintableText
не читает текст из файла. Ему не важно, откуда именно берется текст. Он делегирует чтение текста инкапсулированному экземпляру Text
. Как этот инкапсулированный объект будет обрабатывать текст и откуда его будет получать, PrintableText
не интересует.
Продолжим и попробуем создать реализацию Text
, которая будет делать все буквы в тексте заглавными:
Как насчет Текста
, который обрезает ввод:
Я могу продолжать с этими декораторами. Я могу создавать множество из них, подходящих для своих собственных индивидуальных случаев использования. Но давайте посмотрим, как они все могут взаимодействовать друг с другом. Допустим, я хочу прочитать текст из файла, сделать его заглавными буквами, обрезать его и удалить все непечатные символы. И я хочу, чтобы это было декларативно. Вот что я делаю:
Сначала я создаю экземпляр Text
, составляя несколько декораторов в один объект. Я декларативно определяю поведение text
, не выполняя ничего на самом деле. Пока не вызван метод read()
, файл не будет изменен, и обработка текста не начнется. Объект text
является просто составным объектом декораторов, а не исполняемой процедурой. Посмотрите эту статью о декларативном и императивном стилях программирования: Утилитарные классы не имеют ничего общего с функциональным программированием.
Этот дизайн намного более гибкий и повторно используемый, чем более традиционный, где объект Text
достаточно умный, чтобы выполнять все указанные операции. Например, класс String
в Java является хорошим примером плохого дизайна. Он имеет более 20 утилитарных методов, которые вместо этого должны были быть предоставлены в виде декораторов: trim()
, toUpperCase()
, substring()
, split()
и многие другие, например. Когда я хочу обрезать строку, привести ее к верхнему регистру и затем разделить на части, мой код будет выглядеть так:
Это императивное и процедурное программирование. С другой стороны, композируемые декораторы сделали бы этот код объектно-ориентированным и декларативным. Было бы здорово иметь что-то подобное в Java (псевдокод):
В заключение, я рекомендую вам хорошенько подумать каждый раз, когда вы добавляете новый вспомогательный метод в интерфейс/класс. Старайтесь избегать использования вспомогательных методов насколько это возможно и вместо этого используйте декораторы. Идеальный интерфейс должен содержать только методы, которые вы абсолютно не можете удалить. Все остальное должно быть реализовано с помощью комбинируемых декораторов.
Translated by ChatGPT gpt-3.5-turbo/42 on 2023-11-17 at 16:42