觀察者模式舉例

來源:互聯網
上載者:User

http://jasonshieh.javaeye.com/blog/726557

 

package observe;

import java.util.Vector;

interface Observer {
 public void update();
}

interface Subject {
 public void attach(Observer o);

 public void detach(Observer o);

 public void notice();
}

class Teacher implements Subject {
 private String phone;
 private Vector students;

 public Teacher() {
  phone = "";
  students = new Vector();
 }

 public void attach(Observer o) {
  students.add(o);
 }

 public void detach(Observer o) {
  students.remove(o);
 }

 public void notice() {
  for (int i = 0; i < students.size(); i++)
   ((Observer) students.get(i)).update();
 }

 public void setPhone(String phone) {
  this.phone = phone;
  notice();
 }

 public String getPhone() {
  return phone;
 }
}

class Student implements Observer {
 private String name;
 private String phone;
 private Teacher teacher;

 public Student(String name, Teacher t) {
  this.name = name;
  teacher = t;
 }

 public void show() {
  System.out.println("Name:" + name + "/nTeacher'sphone:" + phone);
 }

 public void update() {
  phone = teacher.getPhone();
 }
}

public class Client {
 public static void main(String[] args) {
  Vector students = new Vector();
  Teacher t = new Teacher();
  for (int i = 0; i < 5; i++) {
   Student st = new Student("lili" + i, t);
   students.add(st);
   t.attach(st);
  }
  
  t.setPhone("88803807");
  for (int i = 0; i < 5; i++)
   ((Student) students.get(i)).show();
 }

 

觀察者模式可以參考郵件訂閱的例子
郵件訂閱設計到2個主要角色,一個是訂閱者(觀察者),一個是發行者

發行者可以擁有一個觀察者的集合,可以添加,刪除觀察者,當發行者發布一個新的訊息時,要郵件通知觀察者集合中的每一個。
所以,發行者實現的介面至少應具備三個方法,即註冊觀察者,登出觀察者,通知觀察者。

通知有兩種方式,一種是推(push),一種是拉(pull).
推,即發行者通過調用觀察者提供的介面,來通知觀察者一些變動(比如新增一個訊息)。
拉,即觀察者可以自主提取所要接受的資料,而不是全盤接受,主要體現在觀察者程式自己主動調用觀察者的傳值介面,而區別於推由發行者來調用,此時,需要這個介面中的參數包含發行者對象,讓程式知道掃描變動來自於哪個發行者。

JDK中內建了觀察者模式,位於java.util包中,一個介面Observer,一個類Observable,將這兩個類組合起來使用,既可以推,又可以拉。
一個普通的類,如果繼承了Observable,就成了一個發行者,實現了Observer介面,就成了觀察者。
JDK中的觀察者模式有一個弊端,就是發行者需要繼承一個類,而不是實現一個介面,如果需要成為發行者的類已經整合了一個類,就不能再繼承Observable了。這時候,就需要自己來設計一種觀察者模式了。

JDK 中Swing包中,大量運用了觀察者模式,所有的組件都繼承了JComponent,這就是一個發行者,它裡麵包含一個監聽器的集合:EventListenerList,使用者可以自訂一個監聽器,然後添加到一個組件中的時候,該組件就會把這個監聽器註冊到 EventListenerList中,相當於添加了一個發行者,當使用者對組件做出反應(如單擊)時,相關的監聽器(接受者)都會收到資訊並作出反應。

 

 

Observable提供必要的資訊.
Observer(Listener)則對Observer所提供的資料做自己感興趣的處理 .
比如TimeSource提供時間這一資料,TimeSink可以獲所得TimeSource提供的時間資料,有人可能要實現數字時鐘,另外有人可能想使用所提供的時間實現一個提醒服務。還有人可能想啟動每晚備份功能。簡而言之,希望一個單一的TimeSource對象能夠為多個TimeSink對象提供時間.

Observable與Observer關係,如果1 : 1則可以做成依賴關係,  如果1 : n 則在Observable 內儲存一個Observer的集合。
當然也可以利用第三個類來建立這二者的關係.Tomcat的Session與SessionListener就是利用第三個類建立二者的關係.

Observer的推模型和拉模型 。
推模型是通過把資料傳給 notify和update方法從而把資料從目標(subject)推給觀察者(observer). 
拉模型沒有給notify和update方法傳遞任何資料,資料是在觀察者對象收到更新訊息後,查詢被觀察者對象得到的.
在資料量比較大時推模型更合適。
資料量比較小時拉模型比較合適.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.