Статьи

Java EE пересматривает шаблоны проектирования: наблюдатель

Помимо реализации на многих языках и во многих приложениях, Observer Pattern является частью Java с версии 1.0. Шаблон Observer также является хорошей реализацией Голливудского принципа . Точно так же, как агенты в Голливуде любят отозвать кандидатов на роль, а не звонить ежедневно, чтобы спросить о доступных вакансиях, большинство ресурсов на стороне сервера, таких как передача доступных данных соответствующему клиенту, вместо того, чтобы запрашивать обновления вовремя интервал.

Такие запросы с временным интервалом могут потреблять много ресурсов на сервере, а также вызывать больший сетевой трафик, чем фактически необходимо. Хотя Java поддерживала шаблон Observer начиная с 0-го дня, он всегда считается не самой лучшей реализацией (посмотрите на Observer и Observable ). Нахождение в мире JavaEE может даже усложнить ситуацию. Однако JavaEE6 поставляется с альтернативой.

JavaEE6 предлагает аннотацию @Observable как простую готовую реализацию Observer Pattern. Давайте посетим предыдущий пост и расширим его, чтобы использовать наблюдателей.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.devchronicles.observer;
 
 
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.enterprise.event.Event;
import javax.inject.Inject;
 
 
/**
 *
 * @author Murat Yener
 */
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class EventService {
    @Inject
    private String message;
     
    @Inject
    Event<String> event;
     
    public void startService(){
        System.out.println("start service call "+message);
        event.fire("this is my "+message);
        System.out.println("done...");
    }
}

Класс EventService будет внедрен в объект Event типа String, который можно использовать для запуска объектов String. Если вы не читали предыдущий пост, объект сообщения является строкой, которая будет создана фабрикой и введена в класс EventService. Чтобы упростить его, вы можете просто ввести любую строковую константу в переменную с именем message.

Поскольку мы уже закончили с наблюдаемой частью, теперь пришло время создать наблюдателя для прослушивания наших событий.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package com.devchronicles.observer;
 
 
import javax.ejb.Stateless;
import javax.enterprise.event.Observes;
 
 
/**
 *
 * @author Murat Yener
 */
@Stateless
public class EventObserver {
 
 
    public void doLogging(@Observes String message){
        System.out.println("Observed:"+message);
    }
}

Аннотация «Обзоры» помечает метод как наблюдатель для событий String. Если вы запустите сервер и запустите метод обслуживания start, вы поймете, как волшебным образом строка будет введена в класс EventService и чем она будет запущена там, где ее будет предупреждать (наблюдает) класс EventObserver. Удивительно, но это все, что вам нужно для реализации шаблона наблюдателя в JavaEE6.

Как было показано ранее, JavaEE6 предлагает простой способ реализации шаблона Observer. После публикации поста я получил несколько вопросов о том, как различать строковые типы, которые запускаются и наблюдаются.

Хотя в реальных сценариях вы, вероятно, не будете стрелять и наблюдать простые строки, а будете иметь собственные объекты, которые будут наблюдаться по их типу, все же довольно легко различить объекты одного типа и настроить разных наблюдателей для их прослушивания.

Сначала давайте начнем с части, чтобы дифференцировать простые строки.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.devchronicles.observer;
 
 
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
 
 
/**
 *
 * @author Murat Yener
 */
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.PARAMETER})
public @interface MyEvent {
     
    Type value();
     
    enum Type{
        LOGGING, MESSAGE
    }
}

Приведенный выше интерфейс будет действовать как аннотация, чтобы пометить строку, которую нужно запустить, а затем наблюдать, просто пометив соответствующие части.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.devchronicles.observer;
 
 
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.enterprise.event.Event;
import javax.inject.Inject;
 
 
/**
 *
 * @author Murat Yener
 */
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class EventService {
    @Inject
    private String message;
     
    @Inject @MyEvent(MyEvent.Type.LOGGING)
    Event<String> event;
 
 
    @Inject @MyEvent(MyEvent.Type.MESSAGE)
    Event<String> anotherEvent;
     
    public void startService(){
        System.out.println("start service call "+message);
        event.fire("this is my "+message);
        System.out.println("done...");
        anotherEvent.fire("done with the service!");
    }
}

Мы просто добавляем аннотацию MyEvent с нужным типом и позже запускаем события, как мы делали раньше. Части, помеченные красным, — это все, что мы добавили в пример из предыдущего поста.

Теперь давайте аннотируем часть наблюдателя. Опять же, мы просто добавим красные части к предыдущему примеру.

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.observer;
 
import javax.ejb.Stateless;
import javax.enterprise.event.Observes;
 
/**
 *
 * @author Murat Yener
 */
@Stateless
public class EventObserver {
 
    public void doLogging(@Observes @MyEvent(MyEvent.Type.LOGGING) String message){
        System.out.println("Observed:"+message);
    }
 
 
 
    public void doLogging(@Observes @MyEvent(MyEvent.Type.MESSAGE) String message){
        System.out.println("Observed another type of message:"+message);
    }
}

Это все, что вам нужно, чтобы различать даже объекты одного и того же типа для наблюдения.

Ссылка: JavaEE Revisits Design Patterns: Observer , JavaEE Revisits Design Patterns: Observer, часть 2 от нашего партнера по JCG Мурата Йенера в блоге Developer Chronicles .