public String getSearchText() { return searchText; }
public String[] getResults() { return results; }
}
注意LookupEvent类是不可变的。这是很重要的,因为我们并不知道在传递过程中谁将处理这些事件。除非我们创建事件的保护拷贝来传递给每一个监听者,我们需要把事件做成不可变的。如果不这样,一个监听者可能会无意或者恶意地修订事件对象,并破坏系统。 现在我们需要在LookupManager上调用lookupComplete()事件。我们首先要在LookupManager上添加一个LookupListener的集合: List listeners = new ArrayList();
当动作发生时,我们需要调用监听者的代码。在我们的例子中,我们将在查找返回时触发一个lookupCompleted()事件。这意味着在监听者集合上迭代,并使用一个LookupEvent事件对象调用它们的lookupCompleted()方法。 我喜欢把这些代码析取到一个独立的方法fire[event-method-name] ,其中构造一个事件对象,在监听器集合上迭代,并调用每一个监听器上的适当的方法。这有助于隔离主要逻辑代码和调用监听器的代码。下面是我们的fireLookupCompleted方法: privatevoid fireLookupCompleted(String searchText, String[] results){ LookupEvent event = new LookupEvent(searchText, results); Iterator iter = new ArrayList(listeners).iterator(); while (iter.hasNext()) { LookupListener listener = (LookupListener) iter.next(); listener.lookupCompleted(event); } }
第2行代码创建了一个新的集合,传入原监听器集合。这在监听器响应事件后决定在LookupManager中去除自己时将发挥作用。如果我们不是安全地拷贝集合,在一些监听器应该 被调用而没有被调用时发生令人厌烦的错误。 下面,我们将在动作完成时调用fireLookupCompleted辅助方法。这是lookup方法的返回查询结果的结束处。所以我们可以改变lookup方法使其触发一个事件而不是返回字串数组本身。下面是新的lookup方法: publicvoid lookup(String text) { //mimic the server call delay... try { Thread.sleep(5000); } catch (Exception e){ e.printStackTrace(); } //imagine we got this from a server String[] results = new String[]{"Book one", "Book two", "Book three"}; fireLookupCompleted(text, results); }
现在让我们把监听器添加到LookupManager。我们希望当查找返回时更新文本区域。以前,我们只是直接调用setText()方法。因为文本区域是和数据库调用一起都在UI中执行的。既然我们已经将查找逻辑从UI中抽象出来了,我们将把UI类作为一个到LookupManager的监听器,监听lookup事件并相应地更新自己。首先我们将在类定义中实现监听器接口: public class FixedFrame implements LookupListener
接着我们实现接口方法: publicvoid lookupCompleted(final LookupEvent e) { outputTA.setText(""); String[] results = e.getResults(); for (int i = 0; i < results.length; i++) { String result = results[i]; outputTA.setText(outputTA.getText() + "/n" + result); } }
最后,我们将它注册为LookupManager的一个监听器: public FixedFrame() { lookupManager = new LookupManager(); //here we register the listener lookupManager.addListener(this); initComponents(); layoutComponents(); }
//mimic the server call delay... try { Thread.sleep(5000); } catch (Exception e){ e.printStackTrace(); } //imagine we got this from a server String[] results = new String[]{"Book one", "Book two", "Book three"};
fireLookupCompleted(text, results); }
我们也添加新的触发方法fireLookupStarted()。这个方法等同于fireLookupCompleted()方法,除了我们调用监听器上的lookupStarted()方法,并且该事件也不包含结果集。下面是代码: privatevoid fireLookupStarted(String searchText){ LookupEvent event = new LookupEvent(searchText); Iterator iter = new ArrayList(listeners).iterator(); while (iter.hasNext()) { LookupListener listener = (LookupListener) iter.next(); listener.lookupStarted(event); } }