代码之家  ›  专栏  ›  技术社区  ›  Manoj

Java中的用户定义侦听器

  •  8
  • Manoj  · 技术社区  · 14 年前

    我的问题是如何写一个听众。 请给我一些这方面的文章。

    4 回复  |  直到 14 年前
        1
  •  22
  •   Andreas Dolk    12 年前

    一个典型的实现可能是这样的:您的对象是可观察的。因此,每当一个(观察到的)值更改时,就会触发一个事件,并通知所有注册的侦听器。其中一个监听器现在被设计成接收通知并创建和发送电子邮件(javamailapi)

    public class Bean implements Observable{
    
      // code to maintain listeners
      private List<Listener> listeners = new ArrayList<Listener>();
      public void add(Listener listener) {listeners.add(listener);}
      public void remove(Listener listener) {listeners.remove(listener);}
    
      // a sample field
      private int field;
      public int getField() {return field;}
      public int setField(int value) {
        field = value;
        fire("field");        
      }
    
      // notification code
      private void fire(String attribute) {
        for (Listener listener:listeners) {
          fieldChanged(this, attribute);
        }
      }
    }
    

    侦听器接口:

    public interface Listener {
      public void fieldChanged(Object source, String attrbute);
    }
    

    可观察界面:

    public interface Observable {
      public void add(Listener listener);
      public void remove(Listener listener);
    }
    

    以及电子邮件:

    public class Sender implements Listener {
    
      public void register(Observable observable) {observable.add(this);}
      public void unregister(Observable observable) {observable.remove(this);}
    
      public void fieldChanged(Object source, String attribute) {
        sendEmail(source, attribute); // this has to be implemented
      }
    
    }
    

    编辑 更正了setter方法中的一个丑陋错误-现在事件被触发 之后

        2
  •  6
  •   Adamski    14 年前

    如果您只是想知道被修改对象的属性,我建议您使用 PropertyChangeListener . 这样你就可以使用 PropertyChangeSupport

    对于更多定制的事件触发,我建议您定义自己的侦听器接口。

    public class MyBean {
      private final PropertyChangeSupport support;
    
      private int i;
      private boolean b;
    
      public MyBean() {
        this.support = new PropertyChangeSupport(this);
      }
    
      // Accessors and Mutators.  Mutating a property causes a PropertyChangeEvent
      // to be fired.
      public int getI() { return i; }
    
      public void setI(int i) {
        int oldI = this.i;
        this.i = i;
        support.firePropertyChange("i", oldI, this.i);
      }
    
      public boolean getB() { return b; }
    
      public void setB(boolean b) {
        boolean oldB = this.b;
        this.b = b;
        support.firePropertyChange("b", oldB, this.b);
      }
    
      // Wrapper methods that simply delegate listener management to
      // the underlying PropertyChangeSupport class.
      public void addPropertyChangeListener(PropertyChangeListener l) {
        support.addPropertyChangeListener(l);
      }
    
      public void addPropertyChangeListener(String propertyName, PropertyChangeListener l) {
        // You would typically call this method rather than addPropertyChangeListener(PropertyChangeListener)
        // in order to register your listener with a specific property.
        // This then avoids the need for large if-then statements within your listener
        // implementation in order to check which property has changed.
    
        if (!"i".equals(propertyName) && !"b".equals(propertyName)) {
          throw new IllegalArgumentException("Invalid property name: " + propertyName);
        }
    
        support.addPropertyChangeListener(propertyName, l);
      }
    
      public void removePropertyChangeListener(PropertyChangeListener l) {
        support.removePropertyChangeListener(l);
      }
    
      public void removePropertyChangeListener(String propertyName, PropertyChangeListener l) {
        support.removePropertyChangeListener(propertyName, l);
      }
    }
    

    // Create a new instance of our observable MyBean class.
    MyBean bean = new MyBean();
    
    // Create a PropertyChangeListener specifically for listening to property "b".
    PropertyChangeListener listener = new PropertyChangeListener() {
      public void propertyChange(PropertyChangeEvent evt) {
        assert "b".equals(evt.getPropertyName());
        boolean oldB = (Boolean) evt.getOldValue();
        boolean newB = (Boolean) evt.getNewValue();
    
        System.err.println(String.format("Property b updated: %b -> %b, oldB, newB));
      }
    }
    
    // Register listener with specific property name.  It will only be called back
    // if this property changes, *not* the "i" int property.
    bean.addPropertyChangeListener("b", listener);
    
        3
  •  3
  •   ToYonos    10 年前

    你应该使用 Observer Design Pattern . 此模式使用以下类:

    public class EmailObserver implements Observer
    {
        @Override
        public void update(Observable obj, Object arg)
        {
            if (obj instanceof YourObject)
            {
                // TODO Send the mail or whatever, you have access to the modified object through obj
                // In arg you can put some additional parameter, like the modified field
            }
        }
    }
    

    public static class YourObject extends Observable
    {
        public void setSomething(Object parameter)
        {
            // TODO some modification in YourObject
    
            setChanged(); // From Observable : the object has changed
            notifyObservers(parameter); // Notify the observer about the change
        }
    }
    

    public static void main(String[] args)
    {
        // Create YourObject
        YourObject o = new YourObject();
    
        // create an observer
        EmailObserver emailObserver = new EmailObserver();
    
        // subscribe the observer to your object
        o.addObserver(emailObserver);
    
        // Now you can modify your object, changes will be notified by email
        o.setSomething(...);
    }