2009-04-30 29 views
0

我试图实现事件生成器成语(http://www.javaworld.com/javaworld/jw-09-1998/jw-09-techniques.html)。尽管如此,我觉得事情在可观察的课堂上有点“奇怪”。比方说,我有以下类:在Java中实现事件生成器成语

 
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-method中的侦听器,当唯一改变的是在接口上调用哪个方法时。因此我做了一个单独的fireEvent方法,并且它正在工作。问题是使fireEvent中的事件参数的数据类型与BakeryListeners中定义的方法保持“同步”。目前fireEvent看起来像这样(节选):

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

...等等。我想我可以用一个枚举,而不是一个字符串,使其无法调用fireEvent与不存在的事件类型,但我仍然必须将Type.RECEIVED映射到listener.orderReceived等?

fireEvent方法可能将BakeryListeners方法作为参数吗?即(伪代码)方法声明:

fireEvent(BakeryListeners.methods eventType, Order source) 

,然后只是直接调用适当的方法内fireEvent(无如果/切换):

call(listener, eventType(source)) 

然后,它也将是不可能建立一个事件谁没有在界面BakeryDAO.takeOrder() - > fireEvent(eventWhoDoesntExist) - >异常中定义?

在Java中可以这样做吗?或者如果我了解错误的事情会更好?

回答

0

在我的这些类型的系统的实现中,我有事件(上面的BakeryEvent)携带有关发生了什么的一些信息,然后让侦听器在接收事件时决定要做什么(如果有的话)。这导致一个简单inteface像

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

在java中不存在,这将支持你在你想被不幸调用的“默认”的方法流程图泛型方法。

莱恩

0

在更清洁的源代码创建每“事件”结果的一个方法,并且因此更容易阅读。不要将太多的信息放入事件对象,而是依赖事件侦听器接口中的方法定义。通过减少已定义方法的数量来试图“优化”源代码是毫无意义的。

此外,这样你就不会遇到可能会调用未知事件的问题。

(完全不同的东西:每次触发事件,但使用CopyOnWriteArrayList时间不克隆听众的名单,很会照顾的,对于你的。)

1

我觉得枚举事件类型和包括事件中的事件类型更清晰,每种​​事件类型都有一个方法。

首先,你要避免所有的贝克听众不得不实施所有的方法,如果他们只对一个事件感兴趣,就把它们留空。 (你有没有实现MouseListener?)

第二,你可以添加到你以后,当你发现你需要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! 

}