Иногда Очень часто мне нужен класс, который реализует интерфейс путем создания экземпляра другого класса. Звучит странно? Позвольте мне показать вам пример. В Takes Framework есть много таких классов, и все они названы как *Wrap . Это удобная концепция дизайна, которая, к сожалению, в Java выглядит довольно многословно. Было бы здорово иметь что-то более короткое, например, в EO .
Север Северо-западом (1959) Альфредом Хичкоком
Взгляните на RsHtml от Takes Framework . Его дизайн выглядит следующим образом (упрощенная версия с одним основным конструктором):
|
01
02
03
04
05
06
07
08
09
10
|
class RsHtml extends RsWrap { RsHtml(final String text) { super( new RsWithType( new RsWithStatus(text, 200), "text/html" ) ); }} |
Теперь давайте посмотрим, что расширяет RsWrap :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public class RsWrap implements Response { private final Response origin; public RsWrap(final Response res) { this.origin = res; } @Override public final Iterable<String> head() { return this.origin.head(); } @Override public final InputStream body() { return this.origin.body(); }} |
Как видите, этот «декоратор» ничего не делает, кроме «просто декорирования». Он инкапсулирует другой Response и проходит через все вызовы методов.
Если пока не ясно, я объясню назначение RsHtml . Допустим, у вас есть текст, и вы хотите создать Response :
|
1
2
3
4
5
|
String text = // you have it alreadyResponse response = new RsWithType( new RsWithStatus(text, HttpURLConnection.HTTP_OK), "text/html"); |
Вместо того, чтобы многократно RsHtml эту композицию декораторов во многих местах, вы используете RsHtml :
|
1
2
|
String text = // you have it alreadyResponse response = new RsHtml(text); |
Это очень удобно, но этот RsWrap очень многословен. Слишком много строк, которые не делают ничего особенного; они просто перенаправляют все вызовы методов в инкапсулированный Response .
Как насчет того, чтобы мы представили новую концепцию «декораторы» с новым ключевым словом decorates :
|
01
02
03
04
05
06
07
08
09
10
|
class RsHtml decorates Response { RsHtml(final String text) { this( new RsWithType( new RsWithStatus(text, 200), "text/html" ) ) }} |
Затем, чтобы создать объект, мы просто вызываем:
|
1
|
Response response = new RsHtml(text); |
У нас нет новых методов в декораторах, только конструкторы. Единственная цель для этих парней — создавать другие объекты и инкапсулировать их. Они на самом деле не являются объектами полного назначения. Они только помогают нам создавать другие объекты.
Вот почему я бы назвал их «украшением конвертов».
Эта идея может выглядеть очень похожей на шаблон проектирования Factory , но в ней нет статических методов , которых мы стараемся избегать в объектно-ориентированном программировании .
Вы можете также найти эти связанные посты интересными: Композитные декораторы против императивных утилитарных методов ; Защитное программирование через валидацию декораторов ; If-Then-Else — это запах кода ; Вертикальная и горизонтальная отделка ; Почему дизайн InputStream неправильный ;
| Ссылка: | Оформление конвертов от нашего партнера по JCG Егора Бугаенко в блоге About Programming . |
