觀察者模式基礎
以下是小孩哭這個動作,通知所觀察者(Mum Dad Dog)做出不同的反應
/** * 分離觀察者與被觀察者 */ class Child { private boolean cry = false; private List<Observer> observers = new ArrayList<>(); { observers.add(new Dad()); observers.add(new Mum()); observers.add(new Dog()); } public boolean isCry() { return cry; } public void wakeUp() { cry = true; for(Observer o : observers) { o.actionOnWakeUp(); } } } /**定義主題對象接口 觀察者接口**/ interface Observer { void actionOnWakeUp(); } class Dad implements Observer { public void feed() { System.out.println("dad feeding..."); } @Override public void actionOnWakeUp() { feed(); } } class Mum implements Observer { public void hug() { System.out.println("mum hugging..."); } @Override public void actionOnWakeUp() { hug(); } } class Dog implements Observer { public void wang() { System.out.println("dog wang..."); } @Override public void actionOnWakeUp() { wang(); } } public class Main { public static void main(String[] args) { Child c = new Child(); //do sth c.wakeUp(); } }
dad feeding...
dog wang...
mum hugging...
觀察者模式本身比較簡單 就是多態的應用
很多時候 觀察者需要根據這件事的具體情況做出相應的處理:比如小孩哭的時間和地點,觀察者做出的反應應該不同
下面對觀察者模式進行進一步的封裝
抽象出處理事件類
把小孩哭得所有狀況傳到一個事件里面
//事件類 fire Event class wakeUpEvent{ long timestamp; String loc; public wakeUpEvent(long timestamp, String loc) { this.timestamp = timestamp; this.loc = loc; } } interface Observer { void actionOnWakeUp(wakeUpEvent event); }
有點類似發布訂閱,發布者發布一個事件,訂閱者接收這個事件
事件類增加事件源對象,並形成繼承體系
大多數時候,我們處理事件的時候,需要事件源對象(有時觀察者需要事件原對象的一些資源)
class wakeUpEvent{ long timestamp; String loc; Child source; public wakeUpEvent(long timestamp, String loc, Child source) { this.timestamp = timestamp; this.loc = loc; this.source = source; } }
因為我們都是面向接口編程 所以把事件定義一個接口或者抽象類。這也是多態的應用
abstract class Event<T> { abstract T getSource(); } class wakeUpEvent extends Event<Child>{ long timestamp; String loc; Child source; public wakeUpEvent(long timestamp, String loc, Child source) { this.timestamp = timestamp; this.loc = loc; this.source = source; } @Override Child getSource() { return source; } }
其實Observer Listener Hook CallBack 這些都是觀察者模式
最終代碼

package com.mashibing.dp.observer.v8; import java.util.ArrayList; import java.util.List; /** * 有很多時候,觀察者需要根據事件的具體情況來進行處理 * 大多數時候,我們處理事件的時候,需要事件源對象 * 事件也可以形成繼承體系 */ class Child { private boolean cry = false; private List<Observer> observers = new ArrayList<>(); { observers.add(new Dad()); observers.add(new Mum()); observers.add(new Dog()); observers.add((e)->{ System.out.println("ppp"); }); //hook callback function } public boolean isCry() { return cry; } public void wakeUp() { cry = true; wakeUpEvent event = new wakeUpEvent(System.currentTimeMillis(), "bed", this); for(Observer o : observers) { o.actionOnWakeUp(event); } } } abstract class Event<T> { abstract T getSource(); } class wakeUpEvent extends Event<Child>{ long timestamp; String loc; Child source; public wakeUpEvent(long timestamp, String loc, Child source) { this.timestamp = timestamp; this.loc = loc; this.source = source; } @Override Child getSource() { return source; } } interface Observer { void actionOnWakeUp(wakeUpEvent event); } class Dad implements Observer { public void feed() { System.out.println("dad feeding..."); } @Override public void actionOnWakeUp(wakeUpEvent event) { feed(); } } class Mum implements Observer { public void hug() { System.out.println("mum hugging..."); } @Override public void actionOnWakeUp(wakeUpEvent event) { hug(); } } class Dog implements Observer { public void wang() { System.out.println("dog wang..."); } @Override public void actionOnWakeUp(wakeUpEvent event) { wang(); } } public class Main { public static void main(String[] args) { Child c = new Child(); //do sth c.wakeUp(); } }
ApplicationListener
Spring中的ApplicationListener也是使用的觀察者模式,下面兩種方式做比較