На этот раз в прошлом году я написал серию постов в блоге о реализации шаблонов проектирования 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 decoratorpublic 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 */@Decoratorpublic 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 .