На этот раз в прошлом году я написал серию постов в блоге о реализации шаблонов проектирования JavaEE. Примерно через год я понял, что скучаю по своей любимой модели — декоратору.
Шаблон декоратора — это в основном способ расширить функциональность объекта, украшая его другими объектами, которые могут обернуть целевой объект и добавить к нему свое собственное поведение. Если вы никогда не пользовались декораторами или не слышали о них, я настоятельно рекомендую прочитать главу 3 главы «Образцы проектирования в первую очередь».
Подобно другим шаблонам, упомянутым в моих постах ранее, JavaEE предлагает простой и элегантный способ использования шаблона декоратора. Начнем с простого сессионного компонента без сохранения состояния.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
package com.devchronicles.decorator; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; /** * * @author murat */ @Stateless @TransactionAttribute (TransactionAttributeType.REQUIRED) public class EventService { public void startService(){ System.out.println( "do something important here..." ); } } |
Чтобы начать реализацию шаблона декоратора, нам нужен интерфейс, чтобы мы могли связать декораторы и объект, который будет оформлен вместе.
1
2
3
4
5
6
7
8
9
|
package com.devchronicles.decorator; /** * * @author murat */ public interface ServiceInterface { public void startService(); } |
В интерфейсе есть метод, с которым декораторы будут добавлять функциональность. Затем нам нужно внести некоторые изменения в существующий компонент EventService, чтобы сделать его пригодным для декорирования.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
package com.devchronicles.decorator; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; /** * * @author murat */ @Stateless @TransactionAttribute (TransactionAttributeType.REQUIRED) public class EventService implements ServiceInterface{ public void startService(){ System.out.println( "do something important here..." ); } } |
Теперь мы готовы добавить столько декоратора, сколько нам нужно. Все, что нам нужно сделать, это аннотировать наш класс, реализовать ServiceInterface и внедрить наш делегат службы.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package com.devchronicles.decorator; import javax.decorator.Decorator; import javax.decorator.Delegate; import javax.inject.Inject; /** * * @author murat */ @Decorator //declares this class as a decorator public class DecoratorService implements ServiceInterface{ //must implement the service interface @Inject //inject the service @Delegate //and annotate as the delegate ServiceInterface service; @Override public void startService() { //implement the startService method to add functionality System.out.println( "decorating the existing service!" ); service.startService(); //let the execution chain continue } } |
Несколько декораторов могут использовать интерфейс сервиса.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.devchronicles.decorator; import javax.decorator.Decorator; import javax.decorator.Delegate; import javax.inject.Inject; /** * * @author murat */ @Decorator public class Decorator2Service implements ServiceInterface{ @Inject @Delegate ServiceInterface service; @Override public void startService() { System.out.println( "decorating the service even further!!!" ); service.startService(); } } |
Большая часть конфигурации может быть выполнена с помощью аннотации в JavaEE6. Однако нам все еще нужно добавить некоторую конфигурацию xml, чтобы декораторы работали. Это может показаться разочаровывающим, поскольку мы уже аннотировали наши декораторы, но конфигурация все еще довольно проста и необходима для объявления порядка выполнения. Добавьте следующие строки в пустой файл beans.xml.
1
2
3
4
5
6
7
8
9
|
<? xml version = "1.0" encoding = "UTF-8" ?> xsi:schemaLocation = "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd" > < decorators > < class >com.devchronicles.decorator.DecoratorService</ class > < class >com.devchronicles.decorator.Decorator2Service</ class > </ decorators > </ beans > |
Когда метод startService нашего EventService будет выполнен, декораторы украсят ejb и добавят свое поведение к выполнению.
1
2
3
4
5
6
7
8
|
... INFO: WEB0671: Loading application [Decorator] at [ /Decorator ] INFO: Decorator was successfully deployed in 2,534 milliseconds. INFO: decorating the existing service! INFO: decorating the service even further!!! INFO: do something important here... ... |
Ссылка: JavaEE пересматривает шаблоны проектирования: Декоратор от нашего партнера по JCG Мурата Йенера в блоге Developer Chronicles .