Реализация идиомы Event-Generator в Java - PullRequest
0 голосов
/ 30 апреля 2009

Я пытаюсь реализовать идиому Event Generator (http://www.javaworld.com/javaworld/jw-09-1998/jw-09-techniques.html). Я нахожу вещи немного странными, когда дело доходит до наблюдаемого класса. Допустим, у меня есть следующие классы:

interface BakeryListener  
+ orderReceived(BakeryEvent event)  
+ orderProcessing(BakeryEvent event)  
+ orderFinished(BakeryEvent event)  
+ orderDelivered(BakeryEvent event)  

LogView, OrderReadyView etc. implements BakeryListener  
Creates a GUI for each own use

Order  
VO / DTO object, used as the source in BakeryEvent 

BakeryDAO (the observable)  
- orders : Vector  
- listeners : Vector  
+ takeOrder, cancelOrder, bake and other regular DAO methods, 
triggering an event by calling fireEvent
+ addBakeryListener(BakeryEvent event)  
+ removeBakeryListener(BakeryEvent event)  
- fireEvent(Order source, EVENTTYPE????)

BakeryGUI  
Creates/gets a reference to BakeryDAO. Creates and attaches LogView, OrderReadyView as listeners on BakeryDAO.

В приведенной мной ссылке он рекомендует «Назовите метод пропаганды событий fire [listener-method-name]». Я считаю это избыточным: создание снимка и перебор слушателей в каждом методе fire, когда единственное, что меняется, - это какой метод вызывать на интерфейсе. Таким образом, я сделал единственный метод fireEvent, и он работает вроде. Проблема заключается в том, чтобы сохранять тип данных параметра события в fireEvent «синхронно» с методами, определенными в BakeryListeners. В настоящее время fireEvent выглядит следующим образом (отрывок):

for(BakeryListener listener : copyOfListeners){
    if(eventType.equals("received")) listener.orderReceived(event);
    else if(eventType.equals("processing")) listener.orderProcessing(event);
}

... и т. Д. Я думаю, я мог бы использовать enum вместо строки, чтобы сделать невозможным вызов fireEvent с несуществующим eventType, но мне все еще нужно сопоставить Type.RECEIVED с listener.orderReceived и т. Д.?

Возможно ли, чтобы метод fireEvent принял методы BakeryListeners в качестве параметра? I.e (псевдокод) объявление метода:

fireEvent(BakeryListeners.methods eventType, Order source)

, а затем просто вызовите соответствующий метод непосредственно внутри fireEvent (без if / switch):

call(listener, eventType( source)) 

Тогда также было бы невозможно создать событие, которое не определено в интерфейсе BakeryDAO.takeOrder () -> fireEvent (eventWhoDoesntExist) -> исключение?

Возможно ли сделать это на Java? Или лучше, если я неправильно понял?

Ответы [ 3 ]

1 голос
/ 30 апреля 2009

Я думаю, что Перечисление типов событий и включение типа события в Событие является более чистым, чем один метод для каждого типа события.

Сначала вы избегаете от всех слушателей-пекарей необходимости реализовывать все методы, а затем оставляете их пустыми, если они заинтересованы только в одном событии. (Вы когда-нибудь реализовывали MouseListener?)

Во-вторых, вы можете добавить Enum позже, когда узнаете, что вам нужны orderBilled и orderPaied без добавления дополнительных методов для всех ваших слушателей, которым не требуется обрабатывать события такого типа.

public class BakeryEvent {
  public enum Type { Received, Processing,Finished,Delivered,Billed,Paied };

  private Type myType;
  private Order myOrder;

  BakeryEvent( Order order, BakeryEvent.Type bet ) {//...

  }
  //...
}


public interface BakeryListener {
  public void handleBakeryEvent( BakeryEvent be );
}

Тогда

public class OvenScheduler implements BakeryListener {

  public void handleBakeryEvent( BakeryEvent be ){
    if ( BakeryEvent.Type.Received.equals(be.getEventType() ) {
      scheduldeOven( be.getOrder() );
    }
  }
  // hey look I don't have to implement orderBilled() and then do nothing!

}
0 голосов
/ 30 апреля 2009

Создание одного метода на «событие» приводит к намного более чистому исходному коду и, следовательно, его легче читать. Не помещайте слишком много информации в объект события, вместо этого полагайтесь на определения методов в интерфейсе прослушивателя событий. Нет смысла пытаться «оптимизировать» ваш исходный код, сократив количество определенных методов.

Кроме того, таким образом вы не столкнетесь с проблемой, при которой может быть вызвано неизвестное событие.

(Что-то совершенно другое: не клонируйте список слушателей при каждом запуске события, а используйте CopyOnWriteArrayList , он позаботится об этом за вас.)

0 голосов
/ 30 апреля 2009

В моих реализациях систем такого типа у меня есть событие (BakeryEvent выше), несущее некоторую информацию о том, что произошло, и затем позволяю слушателю решить, что делать (если что-нибудь), когда они получают событие. Это приводит к простому интерфейсу типа

for (Listener l : registeredListeners) {
  l.processEvent(event);
}

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

Len

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...