某一個事件的發生須要通知多個組件的時候。 注意這裏是「多個」,若是是單個組件徹底可使用回調的方式。java
JDK已經幫咱們定義好了觀察者模式的接口(java.util.Observale;java.util.Observer),咱們若是項目中須要使用觀察者模式,只需簡單繼承一下就能夠了,JDK保證了線程安全。程序員
Observable對象維護了一個ArrayList<監聽者>,經過回調通知訂閱者。 主要方法:notifyObservers,addObserver安全
Observer 對象須要實現的方法 update(),供Observable回調使用。ide
java.util.Observale源碼:this
for(Observer observer ; ObserverList){ public void notifyObservers(Object arg) { /* * a temporary array buffer, used as a snapshot of the state of * current Observers. */ 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); }
下面的一個例子是,出版社出版了一個雜誌,要讀者主動訂閱。spa
發佈者線程
public class Publisher extends Observable{ private String magazineName; public String getMagazineName() { return magazineName; } public void setMagazineName(String magazineName) { this.magazineName = magazineName; } public void publish (String magazineName){ this.magazineName = magazineName; this.setChanged(); this.notifyObservers(this); } }
訂閱者code
public class Reader implements Observer { @Override public void update(Observable arg0, Object arg1) { if(arg0 instanceof Publisher){ Publisher publisher = (Publisher)arg0; System.out.println("有新雜誌。我要訂閱"+publisher.getMagazineName()); } } }
public class TestCase { public static void main(String[] args) { // TODO Auto-generated method stub Publisher publisher = new Publisher(); Reader zhangsan = new Reader(); publisher.addObserver(zhangsan); Reader lisi = new Reader(); publisher.addObserver(lisi); publisher.publish("程序員第0321期"); //結果 //有新雜誌。我要訂閱 程序員第0321期 } }
public interface ContentObserver { public void onChange(boolean stateNow); }
定義觀察者server
public class Activity implements ContentObserver{ @Override public void onChange(boolean stateNow) { } }
import java.util.ArrayList; public class Context { private ArrayList<ContentObserver> observerList = new ArrayList<ContentObserver>(); public final void registerContentObserver(ContentObserver observer){ observerList.add(observer); } public final void UnregisterContentObserver(ContentObserver observer){ observerList.remove(observer); } public void notifyChange(boolean state) { for(ContentObserver observer : observerList){ observer.onChange(state); } } }
public static void main(String[] args) { Activity a1 = new Activity1(); Activity a2 = new Activity2(); //context是被觀察者 Context context = new Context(); context.registerContentObserver(a1); context.registerContentObserver(a2); context.notifyChange(false); }
上述代碼的問題是沒有注意線程安全問題,Context中的registerContentObserver、UnregisterContentObserver應該加上Synchronized進行線程同步控制。對象