需求
以支付状态更新通知为例,当支付状态更新时,通知邮件服务和库存服务。
自定义观察者模式
package com.fh.observer;
import org.junit.Test;
import java.util.List;
import java.util.Vector;
/**
* 推送模式
*/
public class ObserverTest6 {
/**
* 观察者
*/
public interface Observer {
void update();
}
/**
* 库存服务
*/
public class MyStockObserver implements Observer {
@Override
public void update() {
System.out.println("库存服务收到通知");
}
}
/**
* 邮件服务
*/
public class MyEmailObserver implements Observer {
@Override
public void update() {
System.out.println("邮件服务收到通知.");
}
}
/**
* 被观察者
*/
public interface Subject {
// 添加观察者
void addObserver(Observer observer);
//删除观察者
void removeObserver(Observer observer);
//通知观察者
void notifyObservers();
}
/**
* 更改支付状态的被观察则
*/
public class MyPaymentStatusUpdateSubject implements Subject {
private List<Observer> observers = new Vector<>();
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
public void updatePaymentStatus(int newStatus) {
// 业务逻辑操作
System.out.println("更新新的支付状态为:" + newStatus);
// 通知观察者
this.notifyObservers();
}
}
@Test
public void m() {
// "支付状态更新"->看做一个事件,可以被监听的事件
// 被观察者。即事件源
MyPaymentStatusUpdateSubject myPaymentStatusUpdateSubject = new MyPaymentStatusUpdateSubject();
// 观察者。即事件监听器
MyEmailObserver myEmailObserver = new MyEmailObserver();
MyStockObserver myStockObserver = new MyStockObserver();
// 添加观察者。
myPaymentStatusUpdateSubject.addObserver(myEmailObserver);
myPaymentStatusUpdateSubject.addObserver(myStockObserver);
// 发布事件。支付状态更新。
myPaymentStatusUpdateSubject.updatePaymentStatus(2);
}
}
jdk中的观察者模式
JDK已经帮我们实现了一个观察者模式,事件收集器采用Vector容器保存,操作事件收集器的方法都是线程安全的。
我们针对JDK给出的观察者模式的解决方案总结几点:
1、Observable实现了大部分的逻辑,没有很好地进行抽象,灵活性降低了
2、存在2个潜在的问题:一个刚刚加入的观察者错过了通知;一个刚刚删除的观察者被错误的通知
3、Observable实现的方法采用synchronized,操作同一个方法时串行,可能会存在效率问题
package com.fh.observer;
import org.junit.Test;
import java.util.*;
public class ObserverTest7 {
/**
* 邮件服务
*/
public class EmailObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("邮件服务收到通知");
}
}
/**
* 库存服务
*/
public class StockObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("库存服务收到通知");
}
}
/**
* 支付状态变更做为一个可观察者
*/
public class PaymentStatusObservable extends Observable {
public void updatePaymentStatus(int newStatus) {
// 业务逻辑操作
System.out.println("更新新的支付状态为:" + newStatus);
// 通知观察者
this.setChanged();//需要调用一下这这方法,表示被观察者的状态已发生变更,Observable才会通知观察者
this.notifyObservers();
}
}
//使用JDK中的观察者模式
@Test
public void m() {
// "支付状态更新"->看做一个事件,可以被监听的事件
// 被观察者。即事件源
PaymentStatusObservable paymentStatusObservable = new PaymentStatusObservable();
// 添加观察者
paymentStatusObservable.addObserver(new EmailObserver());
paymentStatusObservable.addObserver(new StockObserver());
// 支付状态变更
paymentStatusObservable.updatePaymentStatus(3);
}
}
JavaBean中的事件驱动
原理解析
javabean规范中提供了一种监听属性变化的事件驱动模型。提供操作Javabean属性的类PropertyChangeSupport和PropertyEditorSupport。
从事件驱动模型的各个构建来分析,PropertyChangeSupport和PropertyEditorSupport都属于事件源,能够产生事件。如果以观察模式的角度来看,则是被观察者
事件监听器实现PropertyChangeListener接口,通过PropertyChangeSupport和PropertyEditorSupport添加到事件队列中。
一旦有Javabean属性发生变化通过调用PropertyChangeSupport#firePropertyChange()、PropertyEditorSupport#firePropertyChange()即可触发监听器处理事件。
package com.fh.observer;
import org.junit.Test;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeEvent;
public class ObserverTest8 {
/**
*从事件驱动模型的各个构建来分析,PropertyChangeSupport和PropertyEditorSupport都属于事件源,能够产生事件。
* 如果以观察模式的角度来看,则是被观察者
*/
public class PaymentStatusUpdateBean {
PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
public void updateStatus(int newStatus) {
// 模拟业务逻辑
System.out.println("支付状态更新: " + newStatus);
// 触发通知 一旦有Javabean属性发生变化通过调用PropertyChangeSupport#firePropertyChange()
propertyChangeSupport.firePropertyChange("paymentStatuUpdate", 0, newStatus);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
}
/**
* 支付状态变更的监听器
*
* 事件监听器实现PropertyChangeListener接口,
* 通过PropertyChangeSupport和PropertyEditorSupport添加到事件队列中。
*/
public class PaymentStatusUpdateListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.printf("支付状态变更. eventName : %s, oldValue : %s, newValue : %s", evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
}
//测试JDK提供的PropertyChangeEvent
@Test
public void m() {
PaymentStatusUpdateBean paymentStatusUpdateBean = new PaymentStatusUpdateBean();
// 添加监听器
paymentStatusUpdateBean.addPropertyChangeListener(new PaymentStatusUpdateListener());
// 更新支付状态
paymentStatusUpdateBean.updateStatus(3);
}
}