观察者模式
&quo
(Gof定义)观察者模式,定义对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,也被称为发布-订阅(Publish-Subscribe)。想必很多都用过rss新闻聚合吧,例如小张和小李订阅了sina rss,那么sina rss可称为Observable(被观察者)或subject,小张和小李就是observer.当sina rss内容更新时会通知小张和小李。我们用一个简单的小程序模拟这个过程。
1.Subject
t;> -subject知道它的观察者。可以有任意多个观察者观察同一个subject。
-提供注册和删除观察者对象的接口。
//Subject.java ,定义了subject接口
package org.days7.subject; import org.days7.observer.Observer; public interface Subject { //注册观察者对象 public void regiterObserver(Observer o); //移除观察者对象 public void removeObserver(Observer o); //通知每一个观察者,状态已变化 public void notifyObservers(); }
2.Observer -为那些在subject发生改变时需获得通知的对象定义一个更新接口。 //Observer.java,Observer接口定义了一个update方法,供observer对象实现,更新状态
package org.days7.observer; public interface Observer { //当subject对象状态变化时,更新观察者对象 public void update(); }
3.ConcreteSubject
-将有关状态存入各ConcreteObserver对象。
-当它的状态发生改变时, 向它的各个观察者发出通知。
//SinaRss.java,实现Subject接口,注册观察者并在状态改变时通知观察者
package org.days7.subject; import java.util.ArrayList; import java.util.Iterator; import org.days7.observer.Observer; public class SinaRss implements Subject { //建一个list用来保存Observer对象 private ArrayList<Observer> observerList = null; private String text = null; //构造函数,new一个list public SinaRss() { observerList = new ArrayList<Observer>(); } //当subject状态变化时,通知每一个观察者 @Override public void notifyObservers() { Iterator<Observer> it = observerList.iterator(); while(it.hasNext()) { Observer observer = it.next(); observer.update(); //更新observer的状态 } } //注册观察者对象 @Override public void regiterObserver(Observer o) { observerList.add(o); } //移除一个观察者对象 @Override public void removeObserver(Observer o) { observerList.remove(o); } //更新状态,并通知每一个观察者 public void setNewText(String text) { this.text = text; //持有更新状态的引用 notifyObservers(); //通知观察者,状态已变化 } //返回该主题的更新状态,方便观察者获取它想要的东西 public String getNewText() { return this.text; //返回subject状态 } }
4.ConcreteObserver(具体观察者)
-持有一个指向ConcreteSubject对象的引用。
-存储有关状态,这些状态应与Subject的状态保持一致。
-实现Observer的更新接口以使自身状态与Subject的状态保持一致。
// Subscriber.java,具体的Observer,实现Observer接口,根据Subject的变化更新自己的状态
package org.days7.observer; import org.days7.subject.SinaRss; import org.days7.subject.Subject; public class Subscriber implements Observer { //更新的内容(subject状态) private String text = null; //在observer对象中保留一个具体的subject对象引用,用来获取更新的内容 private SinaRss rss = null; //构造函数,传入具体的subject对象,持有该对象的引用 public Subscriber(Subject subject) { if(subject instanceof SinaRss) { this.rss = (SinaRss)subject; } this.rss.regiterObserver(this);//注册观察者对象 } //重写observer的update方法 @Override public void update() { this.text = this.rss.getNewText();//获取更新的新闻内容(更新的状态) displayText(); //对更新的状态进行操作,显示更新的内容 } //显示更新内容 private void displayText() { System.out.println("更新新闻:"+this.text); } }
下面来测试一下这个小程序:
//test.java, 测试程序
package org.days7.test; import org.days7.observer.Subscriber; import org.days7.subject.SinaRss; public class Test { /** * 测试程序 */ public static void main(String[] args) { SinaRss rss = new SinaRss(); Subscriber sub = new Subscriber(rss); String text1 = "New Superstar : 小蝴蝶大战外星人"; rss.setNewText(text1); String text2 = "我和java不得不说的故事..."; rss.setNewText(text2); } } Console: 更新新闻:New Superstar : 小蝴蝶大战外星人 更新新闻:我和java不得不说的故事...