Статьи

JavaEE пересматривает шаблоны проектирования: декоратор

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