Иногда Очень часто мне нужен класс, который реализует интерфейс путем создания экземпляра другого класса. Звучит странно? Позвольте мне показать вам пример. В 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 already Response response = new RsWithType( new RsWithStatus(text, HttpURLConnection.HTTP_OK), "text/html" ); |
Вместо того, чтобы многократно RsHtml
эту композицию декораторов во многих местах, вы используете RsHtml
:
1
2
|
String text = // you have it already Response 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 . |