設計模式之觀察者模式(Observer Pattern)

來源:互聯網
上載者:User

標籤:style   blog   http   color   os   io   java   ar   strong   

一.什麼是觀察者模式?

把現實世界中的報紙與訂閱者的關係抽象出來就是觀察者模式,一種報紙對應多個訂閱者,訂閱者可以隨時解除訂閱,未訂閱的讀者也可以隨時開始訂閱。一旦有新報紙發布,所有的訂閱者都會收到新內容。

在觀察者模式中,報紙叫做主題Subject,訂閱者叫做觀察者Observer,一個Subject可以被多個Observer關注,Observer可以隨時解除關注,新的Observer也可以隨時關注Subject。Subject內容發生改變時,會通知所有的Observer。

二.舉個例子

很多網路遊戲中都有答題活動,所有參與答題活動的玩家都會同時收到題目資訊(延遲忽略不計),未參與活動的玩家可以中途加入,正在答題的玩家也可以隨時退出。

在此例中,遊戲伺服器就是“一”,玩家是“多”,題目資訊就是在它們之間傳遞的訊息。

怎樣才能設計出滿足以上要求的類?不妨試試觀察者模式。

首先,定義Subject抽象類別:

package ObserverPattern;import java.util.ArrayList;/** * @author ayqy * 定義Subject抽象類別 * */public abstract class Subject {ArrayList<Observer> observers = new ArrayList<Observer>();//觀察者列表/** * 註冊主題 * @param o 申請註冊該主題的Observer */public void registSubject(Observer o){observers.add(o);}/** * 刪除主題 * @param o */public void reomveSubject(Observer o){int index = observers.indexOf(o);observers.remove(index);}/** * 通知所有觀察者 * @param arg 該Subject想要傳遞給Observers的資料 */public void notifyObservers(Object arg){for(Observer o : observers)o.update(this, arg);}}

注意,這裡用了抽象類別而沒有用介面,為什嗎?

因為Subject的行為是fixed的,並不需要由子類來擴充。

-------

類似的,我們定義Observer抽象類別:

package ObserverPattern;/** * @author ayqy * 定義Observer抽象類別 * */public abstract class Observer {Subject subject = null;//定義該Observer所關注的Subjectpublic abstract void update(Subject subject, Object arg);//定義Observer的更新介面}

-------

下面開始實現我們的自訂Subject——GameServer:

package ObserverPattern;/** * @author ayqy * 定義GameServer類,繼承自Subject基類,負責發布題目 * */public class GameServer extends Subject{Question ques;//定義題目public Question getQues() {return ques;}public void setQues(Question q) {this.ques = q;super.notifyObservers(ques);//調用父類方法通知所有Observer}}

P.S.GameServer類的成員變數Question是對題目資訊的簡單封裝,Question類包含題號no與題目內容content兩部分定義,以及一個toString方法,返回題目描述資訊

-------

再實現我們的自訂Observer——Player:

package ObserverPattern;/** * @author ayqy * 定義PlayerA,繼承自Observer基類,負責接收新題目 * */public class PlayerA extends Observer{public PlayerA(Subject sub){subject = sub;}@Overridepublic void update(Subject subject, Object arg) {Question q = (Question)arg;System.out.println("PlayerA received " + q.toString());}}

P.S.為了使類層次更加清晰,此處並沒有定義Player基類

很容易複製粘貼得到PlayerB與PlayerC,不再贅述

至此,我們的類比答題活動準備工作已經結束了,下面我們需要定義一個測試類別來展示觀察者模式的魅力。

三.效果樣本

定義如下Test類:

package ObserverPattern;/** * @author ayqy * 實現一個測試類別,類比網路遊戲答題活動(遊戲伺服器按時更新題目資訊並通知所有參與答題的玩家) * */public class Test {public static void main(String[] args){System.out.println("答題活動即將開始。。");//建立伺服器GameServer gs = new GameServer();//建立玩家ABCObserver playerA = new PlayerA(gs);Observer playerB = new PlayerB(gs);Observer playerC = new PlayerC(gs);//為AB註冊Subject,C對答題不感興趣,拒絕註冊gs.registSubject(playerA);gs.registSubject(playerB);System.out.println("玩家AB成功參與答題活動。。");System.out.println("答題活動正式開始。。");gs.setQues(new Question(1, "第一題"));gs.setQues(new Question(2, "第二題"));System.out.println("玩家A不想玩了,退出答題活動。。");gs.reomveSubject(playerA);gs.setQues(new Question(3, "第三題"));System.out.println("玩家C想中途加入活動");gs.registSubject(playerC);gs.setQues(new Question(4, "第四題"));System.out.println("答題活動結束。。");}}

結果樣本:

四.總結

從上面的例子可以看出觀察者模式的特點:

1.利用觀察者模式可以輕易地建立對象之間“一對多”的依賴關係

2.利用觀察者模式的機制可以很容易的實現這種依賴關係的動態維護

設計模式之觀察者模式(Observer Pattern)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.