返回 导航

其他

hangge.com

Java - 使用Observer实现观察者模式、EventListener实现监听器模式详解

作者:hangge | 2023-02-01 08:40
    JDK 不仅提供了 Observable 类、Observer 接口用来支持观察者模式,而且也提供了 EventObjectEventListener 接口来支持事件监听模式。虽然两者属于同一类型模式,都属于回调机制、主动推送消息,但使用场景有些区别,或者说监听器模式是观察者模式在特定场景下的一种改造和应用。下面通过样例分别进行介绍。

一、使用 Observer 实现观察者模式

1,基本介绍

(1)观察者模式又叫做“发布-订阅模式“或者“模型-视图模式”。该模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
(2)通过 java.util.Observable 类和 java.util.Observer 接口可以实现观察者模式。

2,使用样例

(1)下面我们以消息订阅功能进行演示,即当消息更新时,所有观察者都会收到最新消息。首先我们继承 Observable 类实现具体的主题类:
// 具体主题
class ConcreteSubject extends Observable {
  // 当前状态
  private String state;

  // 获取状态
  public String getState() {
    return state;
  }

  // 修改状态
  public void setState(String state) {
    this.state = state;
    // 标记状态已更改
    setChanged();
    // 通知观察者
    notifyObservers(this.state);
  }
}

(2)接着实现 Observer 接口定义具体的观察者类:
// 具体观察者
class ConcreteObserver implements Observer {
  // 观察者名字
  private String name;

  public ConcreteObserver(String name){
    this.name = name;
  }

  // 更新方法
  @Override
  public void update(Observable o, Object arg) {
    System.out.println(this.name + "收到消息:" + (String)arg);
  }
}

(3)最后我们创建 1 个主题,2 个观察者对象测试一下:
public class Test {
  public static void main(String[] args) {
    // 定义1个主题
    ConcreteSubject subject = new ConcreteSubject();
    // 定义2个观察者
    Observer observer1 = new ConcreteObserver("用户1");
    Observer observer2 = new ConcreteObserver("用户2");
    // 注册2个观察者
    subject.addObserver(observer1);
    subject.addObserver(observer2);
    // 更新主题状态
    subject.setState("Welcome to hangge.com");
    // 删除1个观察者
    subject.deleteObserver(observer1);
    // 再次更新主题状态
    subject.setState("欢迎访问 hangge.com");
  }
}

二、使用 EventListener 实现监听器模式

1,基本介绍

(1)监听器模式将对象分为了三个模块:EventSource(事件源)、Event(事件)、EventListener(监听器)。事件源可能会触发多个事件,针对不同的事件都可以定义独立的监听器,当事件源触发事件的时候监听器获得通知并实现用户自定义的业务逻辑。
(2)JDK 中的 java.util.EventListener 是一个标记接口,用于定义事件监听器类。事件监听器类需要注册在事件源上才能被调用。它监听事件,并进行事件处理或者转发。

2,使用样例

(1)下面是用监听器模式对上面的样例进行改造。首先我们定义一个事件类 MyEvent
// 事件类
public class MyEvent{
  // 事件消息内容
  private String message;

  public MyEvent(String message) {
    this.message = message;
  }

  public String getMessage() {
    return message;
  }

  public void setMessage(String message) {
    this.message = message;
  }
}

(2)接着定义了一个名为 MyEventListener 的事件监听器接口,该接口扩展自 EventListener
// 事件监听器接口
public interface MyEventListener extends EventListener {
  // 事件触发响应
  public void eventTriggered(MyEvent event);
}

(3)然后定义了一个名为 MyEventListenerImpl 的事件监听器实现类,它实现了 MyEventListener 接口并重写了 eventTriggered 方法:
// 事件监听器实现类
public class MyEventListenerImpl implements MyEventListener {
  // 监听器名字
  private String name;

  public MyEventListenerImpl(String name){
    this.name = name;
  }

  // 事件监听器触发响应
  @Override
  public void eventTriggered(MyEvent event) {
    // 处理事件
    System.out.println(this.name + "收到消息:" + event.getMessage());
  }
}

(4)此外我们还定义了一个名为 MyEventSource 的事件源,它可以添加或删除 MyEventListener 监听器,并在触发事件时通知所有监听器:
// 事件源
public class MyEventSource {
  // 监听器集合
  private List<MyEventListener> listeners = new ArrayList<>();

  // 添加监听器
  public void addEventListener(MyEventListener listener) {
    listeners.add(listener);
  }

  // 移除监听器
  public void removeEventListener(MyEventListener listener) {
    listeners.remove(listener);
  }

  // 触发事件通知所有监听器
  public void triggerEvent(MyEvent event) {
    for (MyEventListener listener : listeners) {
      listener.eventTriggered(event);
    }
  }
}

(5)最后我们创建 1 个事件源,2 个监听器对象测试一下:
public class Test {
  public static void main(String[] args) {
    // 定义1个事件源
    MyEventSource eventSource = new MyEventSource();
    // 定义2个监听器
    MyEventListener listener1 = new MyEventListenerImpl("用户1");
    MyEventListener listener2 = new MyEventListenerImpl("用户1");
    // 注册监听器
    eventSource.addEventListener(listener1);
    eventSource.addEventListener(listener2);
    // 触发事件
    MyEvent event = new MyEvent("Welcome to hangge.com");
    eventSource.triggerEvent(event);
    // 删除1个监听器
    eventSource.removeEventListener(listener1);
    // 再次触发事件
    event.setMessage("欢迎访问 hangge.com");
    eventSource.triggerEvent(event);
  }
}
评论

全部评论(0)

回到顶部