设计模式——观察者模式

原创
04/27 15:32
阅读数 97

一、基于java.util.Observable和java.util.Ovbserver的 观察者模式基础实现

1. Observable ——抽象的被观察者

package java.util;

/**
 * 源码来自jdk1.0 java.util包
 *
 * @author  Chris Warth
 * @since   JDK1.0
 */
public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs;

    /** Construct an Observable with zero Observers. */

    public Observable() {
        obs = new Vector<>();
    }

    /**
     * 将一个观察者添加到此对象的观察者集合中
     */
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    /**
     * 从该对象的观察者集合中删除一个观察者。
     */
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    /**
     * 如果此对象已更改,如<code> hasChanged <code>方法所示,则通知其所有观察者,
     * 然后调用<code> clearChanged <code>方法以指示该对象不再更改。
     *
     * 每个观察者都实现一个update方法,update方法有两个参数,第一个是当前被观察对象,第二个一个是null 
     */
    public void notifyObservers() {
        notifyObservers(null);
    }

    /**
     * 如果此对象已更改,如<code> hasChanged <code>方法所示,则通知其所有观察者,
     * 然后调用<code> clearChanged <code>方法以指示该对象不再更改。
     *
     * 每个观察者都实现一个update方法,update方法有两个参数,第一个是当前被观察对象,第二个一个是null 
     */
    public void notifyObservers(Object arg) {
        Object[] arrLocal;
        synchronized (this) {
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    /**
     * 清除观察者列表,使该对象不再有任何观察者。
     */
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    /**
     * 将此Observable 对象标记为已更改;hasChanged 方法现在将返回true.
     */
    protected synchronized void setChanged() {
        changed = true;
    }

    /**
     * 指示此对象不再更改,或者它已经将其最近的更改通知了所有观察者,
     * 因此 hasChanged 方法现在将返回false。该方法由<code> notifyObservers <code>方法自动调用。
     */
    protected synchronized void clearChanged() {
        changed = false;
    }

    /**
     * 测试此对象是否已更改。
     */
    public synchronized boolean hasChanged() {
        return changed;
    }

    /**
     * 返回这个的Observable对象的观察者数量。
     */
    public synchronized int countObservers() {
        return obs.size();
    }
}

2. Observer —— 抽象观察者

package java.util;

/**
 * 观察者
 *
 * @author  Chris Warth
 * @see     java.util.Observable
 * @since   JDK1.0
 */
public interface Observer {
    /**
     * 更新自身
     * @param o   被观察对象
     * @param arg  一般是个null
     */
    void update(Observable o, Object arg);
}

接下来我们模拟一个场景,放学铃响了大家会做什么?

3. SchoolBell —— 被观察的实现

/**
 * 学校的铃
 *
 * @author Wilton Jia
 * @date 2021/4/26
 */
public class SchoolBell extends Observable {

    /**
     * 响铃动作
     */
    public void ring(){
        System.out.println("放学铃响了");
        //修改状态
        setChanged();
        //通知所有观察者
        super.notifyObservers();
    }
}

4. T <?extends Observer> —— 观察者的实现

/**
 * 老师
 * @author Wt Jia
 * @date 2021/4/26
 */
public class Teachers implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println(" Teacher 开车回家");
    }
}

/**
 * 学生们
 *
 * @author Wilton
 * @date 2021/4/26
 */
public class Students implements Observer {

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("Student 坐校车回家");
    }

}

/**
 * 门卫大爷
 *
 * @author Wilton
 * @date 2021/4/26
 */
public class Guard implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("Guard 锁学校门");
    }
}

5. ObserverInvoker——调用演示

/**
 * 观察者模式的调用
 *
 * @author Wilton
 * @date 2021/4/26
 */
public class ObserverInvoker {

    public static void main(String[] args) {
        SchoolBell schoolBell = new SchoolBell();

        schoolBell.addObserver(new Teachers());
        schoolBell.addObserver(new Students());
        schoolBell.addObserver(new Guard());

        schoolBell.ring();
    }

}

二、基于JDK的EventObject和EventListener实现观察者模式

Spring中观察者模式的应用就是基于这两个类,但是区别在于这种方式中EventObject无法自己通知到监听者,需要一个第三方通知所有的监听者。

1. EventObject——抽象的事件

public class EventObject implements java.io.Serializable {

    private static final long serialVersionUID = 5516075349620653480L;

    protected transient Object  source;

    public EventObject(Object source) {
        if (source == null)
            throw new IllegalArgumentException("null source");

        this.source = source;
    }

    public Object getSource() {
        return source;
    }

    public String toString() {
        return getClass().getName() + "[source=" + source + "]";
    }
}

/**
 * Spring中事件的抽象实现
 */
public abstract class ApplicationEvent extends EventObject {

	/** 事件发生事件 */
	private final long timestamp;

	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}

	public final long getTimestamp() {
		return this.timestamp;
	}

}


/**
 * 自定义实现事件
 */
public class MyApplicationEvent extends ApplicationEvent {

    public MyApplicationEvent(Object source) {
        super(source);
    }
}


2. ApplicationListener ——Spring中的监听者接口

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * 处理发生的事件
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

/**
 * 自己实现一个
 */
@Component
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {

    @Override
    public void onApplicationEvent(MyApplicationEvent event) {
        System.out.println("MyApplicationEvent happens at : " + event.getTimestamp());
    }
}

3. Spring中的多播器实现 SimpleApplicationEventMulticaster

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

	@Nullable
	private Executor taskExecutor;

	@Nullable
	private ErrorHandler errorHandler;


	/**
	 * 默认构造器
	 */
	public SimpleApplicationEventMulticaster() {
	}

	/**
	 * 带有BeanFaactory的构造器
	 */
	public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
		setBeanFactory(beanFactory);
	}


	/**
	* 一个异步执行器
	 */
	public void setTaskExecutor(@Nullable Executor taskExecutor) {
		this.taskExecutor = taskExecutor;
	}

	@Nullable
	protected Executor getTaskExecutor() {
		return this.taskExecutor;
	}

	/**
	* 如果有异常则使用异常处理器
	 */
	public void setErrorHandler(@Nullable ErrorHandler errorHandler) {
		this.errorHandler = errorHandler;
	}

	@Nullable
	protected ErrorHandler getErrorHandler() {
		return this.errorHandler;
	}


	@Override
	public void multicastEvent(ApplicationEvent event) {
		multicastEvent(event, resolveDefaultEventType(event));
	}

	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}

	private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
		return ResolvableType.forInstance(event);
	}

	/**
	* 通知指定的监听器,发生了某个指定的事件
	 */
	protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
		ErrorHandler errorHandler = getErrorHandler();
		if (errorHandler != null) {
			try {
				doInvokeListener(listener, event);
			}
			catch (Throwable err) {
				errorHandler.handleError(err);
			}
		}
		else {
			doInvokeListener(listener, event);
		}
	}

	@SuppressWarnings({"rawtypes", "unchecked"})
	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
			listener.onApplicationEvent(event);
		}
		catch (ClassCastException ex) {
			String msg = ex.getMessage();
			if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception and just log a debug message.
				Log logger = LogFactory.getLog(getClass());
				if (logger.isTraceEnabled()) {
					logger.trace("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}

	private boolean matchesClassCastMessage(String classCastMessage, Class<?> eventClass) {
		// On Java 8, the message starts with the class name: "java.lang.String cannot be cast..."
		if (classCastMessage.startsWith(eventClass.getName())) {
			return true;
		}
		// On Java 11, the message starts with "class ..." a.k.a. Class.toString()
		if (classCastMessage.startsWith(eventClass.toString())) {
			return true;
		}
		// On Java 9, the message used to contain the module name: "java.base/java.lang.String cannot be cast..."
		int moduleSeparatorIndex = classCastMessage.indexOf('/');
		if (moduleSeparatorIndex != -1 && classCastMessage.startsWith(eventClass.getName(), moduleSeparatorIndex + 1)) {
			return true;
		}
		// Assuming an unrelated class cast failure...
		return false;
	}

}

4. 调用测试

@Component
public class EventMulticasterTestBean implements InitializingBean {

    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;


    @Override
    public void afterPropertiesSet() throws Exception {
        applicationEventMulticaster.multicastEvent(new MyApplicationEvent(new Object()));
    }
}

总结

  1. 对比而言,第一种实现方式较为简单,比较符合正常观察者模式的思维,但是第二种实现方式更加灵活,观察者和被观察对象耦合度比较低,更适用于大型项目。
  2. Spring中的观察者模式贯穿了整个Spring的生命周期,具体可以看观察者模式下的SpringBoot启动过程 这篇帖子了解
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部