開篇
觀察者模式的定義,有多個對象在關注着一個對象,如果這個對象的狀态發生了改變,其它依賴(關注)它的對象就會收到通知,然後在接收到通知以後各個對象做出相應的動作。
觀察者模式涉及到兩個概念(觀察者和被觀察者),被觀察者隻能有一個,而觀察這個觀察者的對象可以用多個。【一對多】定義對象間的一種一對多的依賴關系。當一個對象的狀态發生改變時,所有依賴于它的對象都得到通知并被自動更新。
觀察者模式的demo
被觀察者
- 1.被觀察者對象維護一個觀察者的清單對象和注冊觀察者的接口。
- 2.事件發生變化時候周遊所有觀察者清單并觸發事件。
- 3.觀察者統一實作某接口用以事件通知。
/***
* 抽象被觀察者接口
* 聲明了添加、删除、通知觀察者方法
*
*/
public interface Observerable {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
/**
* 被觀察者,也就是微信公衆号服務
* 實作了Observerable接口,對Observerable接口的三個方法進行了具體實作
*
*/
public class WechatServer implements Observerable {
//注意到這個List集合的泛型參數為Observer接口,設計原則:面向接口程式設計而不是面向實作程式設計
private List<Observer> list;
private String message;
public WechatServer() {
list = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer o) {
list.add(o);
}
@Override
public void removeObserver(Observer o) {
if(!list.isEmpty())
list.remove(o);
}
//周遊
@Override
public void notifyObserver() {
for(int i = 0; i < list.size(); i++) {
Observer oserver = list.get(i);
oserver.update(message);
}
}
public void setInfomation(String s) {
this.message = s;
System.out.println("微信服務更新消息: " + s);
//消息更新,通知所有觀察者
notifyObserver();
}
}
觀察者
- 1.觀察者需要定義統一的接口用以處理事件通知。
/***
* 抽象觀察者
* 定義了一個update()方法,當被觀察者調用notifyObservers()方法時,觀察者的update()方法會被回調。
*
*/
public interface Observer {
public void update(String message);
}
/**
* 觀察者
* 實作了update方法
*
*/
public class User implements Observer {
private String name;
private String message;
public User(String name) {
this.name = name;
}
@Override
public void update(String message) {
this.message = message;
read();
}
public void read() {
System.out.println(name + " 收到推送消息: " + message);
}
}
測試驗證
package com.jstao.observer;
public class Test {
public static void main(String[] args) {
WechatServer server = new WechatServer();
Observer userZhang = new User("ZhangSan");
Observer userLi = new User("LiSi");
Observer userWang = new User("WangWu");
server.registerObserver(userZhang);
server.registerObserver(userLi);
server.registerObserver(userWang);
server.setInfomation("PHP是世界上最好用的語言!");
System.out.println("----------------------------------------------");
server.removeObserver(userZhang);
server.setInfomation("JAVA是世界上最好用的語言!");
}
}
Tomcat實作的觀察者模式
- 1.觀察者實作統一的接口LifecycleListener,實作具體的方法lifecycleEvent。
- 2.觀察者的事件對象繼承了EventObject類,這個有興趣可以研究下。
- 3.觀察者的具體實作以HostConfig為例,實作了具體的lifecycleEvent方法。
public final class LifecycleEvent extends EventObject {
private static final long serialVersionUID = 1L;
public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
super(lifecycle);
this.type = type;
this.data = data;
}
private final Object data;
private final String type;
public Object getData() {
return data;
}
public Lifecycle getLifecycle() {
return (Lifecycle) getSource();
}
public String getType() {
return this.type;
}
}
public interface LifecycleListener {
public void lifecycleEvent(LifecycleEvent event);
}
public class HostConfig implements LifecycleListener {
public void lifecycleEvent(LifecycleEvent event) {
try {
host = (Host) event.getLifecycle();
if (host instanceof StandardHost) {
setCopyXML(((StandardHost) host).isCopyXML());
setDeployXML(((StandardHost) host).isDeployXML());
setUnpackWARs(((StandardHost) host).isUnpackWARs());
setContextClass(((StandardHost) host).getContextClass());
}
} catch (ClassCastException e) {
log.error(sm.getString("hostConfig.cce", event.getLifecycle()), e);
return;
}
if (event.getType().equals(Lifecycle.PERIODIC_EVENT)) {
check();
} else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
beforeStart();
} else if (event.getType().equals(Lifecycle.START_EVENT)) {
start();
} else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
stop();
}
}
}
- 1.被觀察者實作接口Lifecycle,實作addLifecycleListener和removeLifecycleListener方法。
- 2.容器的基類LifecycleBase實作了被觀察者功能,提供List lifecycleListeners儲存被觀察者。
- 3.容器的具體實作當中都是繼承LifecycleBase類,是以天然包含了被觀察者的功能。
package org.apache.catalina;
public interface Lifecycle {
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
}
public abstract class LifecycleBase implements Lifecycle {
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();
private volatile LifecycleState state = LifecycleState.NEW;
public void addLifecycleListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
}
public LifecycleListener[] findLifecycleListeners() {
return lifecycleListeners.toArray(new LifecycleListener[0]);
}
public void removeLifecycleListener(LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}
}