JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Software Design » GoF  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to postflat modego to previous topicgo to next topic
本主題所含的標籤
無標籤
作者 Design Patterns 入門 - 觀察者(Observer) [精華]
caterpillar

良葛格

版主

發文: 2613
積分: 70
於 2003-12-25 23:53 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
此文件已有新版
http://openhome.cc/Gossip/DesignPattern/

假設今天您設計一個試算表程式,當中有一個資料物件,您可以用表格圖形物件、柱狀圖形物件、圓餅圖形物件等方式來呈現物件,無論您是用哪種圖形物件,重點是若資料物件的內容作了更改,則圖形物件的內容也必須跟著修改,或許您的程式中有兩個以上的圖形物件來呈現資料,您在圖形物件上更動資料,則另一個圖形物件也必須作出相對應的變化。

1
2
3
4
5
主題     觀察者
 
     <--> 柱狀圖形
資料物件 <--> 表格圖形
     <--> 圓餅圖形


又假設您今天設計一個網路遊戲,您在伺服器上維護一個連線客戶端共享的資料物件,當其中一個客戶端作了操作,將對此資料物件作修改,則伺服器必須通知其它客戶端作相對應的變化(像是人物位置走動、建了一個城堡等)。

1
2
3
4
5
主題     觀察者
 
     <--> 客戶端圖形介面一
資料物件 <--> 客戶端圖形介面二
     <--> 客戶端圖形介面三


在觀察者(Observer)模式中的主角為主題(subject)與觀察者(observer),觀察者訂閱它感興趣的主題,一個主題可以被多個觀察者訂閱,當主題的狀態發生變化時,它必須通知(notify)所有訂閱它的觀察者,觀察者檢視主題的狀態變化,並作出對應的動作,所以觀察者模式也稱之為「發佈-訂閱」(Publish-Subscribe)模式。

觀察者模式的UML圖如下所示:


Subject類中有一個notify()方法,通常是在Subject的狀態發生改變時呼叫它,notify()中會呼叫Observer的update()方法,通常會先取得Subject的新狀態,然後更新Observer的顯示或行為,這個過程我們可以透過順序圖(Sequence Diagram)來表達:


在Java中支援觀察者模式,要成為觀察者的類必須實作Observer介面,這個介面中定義了一個update()方法,這個方法會被主題物件在通知狀態變化時呼叫,您必須在這個方法中實作您所想要的對應行為。

主題物件會是Observable的子類,在這邊注意兩個重要的方法:setChanged()與notifyObserver()。setChanged()是用來設定主題物件的狀態已經被改變,而notifyObserver()方法會通知所要訂閱主題物件的觀察者,調用其update()方法。

有興趣的話,建議看一下Observable.java中是如何實作的,這有助於瞭解觀察者模式的運作方式,以下列出Observable.java的內容以方便參考:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*
 * @(#)Observable.java  1.35 03/01/23
 *
 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
 
package java.util;
 
/**
 * This class represents an observable object, or "data"
 * in the model-view paradigm. It can be subclassed to represent an 
 * object that the application wants to have observed. 
 * <p>
 * An observable object can have one or more observers. An observer 
 * may be any object that implements interface <tt>Observer</tt>. After an 
 * observable instance changes, an application calling the 
 * <code>Observable</code>'s <code>notifyObservers</code> method  
 * causes all of its observers to be notified of the change by a call 
 * to their <code>update</code> method. 
 * <p>
 * The order in which notifications will be delivered is unspecified.  
 * The default implementation provided in the Observerable class will 
 * notify Observers in the order in which they registered interest, but 
 * subclasses may change this order, use no guaranteed order, deliver 
 * notifications on separate threads, or may guarantee that their
 * subclass follows this order, as they choose.
 * <p>
 * Note that this notification mechanism is has nothing to do with threads 
 * and is completely separate from the <tt>wait</tt> and <tt>notify</tt> 
 * mechanism of class <tt>Object</tt>.
 * <p>
 * When an observable object is newly created, its set of observers is 
 * empty. Two observers are considered the same if and only if the 
 * <tt>equals</tt> method returns true for them.
 *
 * @author  Chris Warth
 * @version 1.35, 01/23/03
 * @see     java.util.Observable#notifyObservers()
 * @see     java.util.Observable#notifyObservers(java.lang.Object)
 * @see     java.util.Observer
 * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
 * @since   JDK1.0
 */
public class Observable {
    private boolean changed = false;
    private Vector obs;
   
    /** Construct an Observable with zero Observers. */
 
    public Observable() {
  obs = new Vector();
    }
 
    /**
     * Adds an observer to the set of observers for this object, provided 
     * that it is not the same as some observer already in the set. 
     * The order in which notifications will be delivered to multiple 
     * observers is not specified. See the class comment.
     *
     * @param   o   an observer to be added.
     * @throws NullPointerException   if the parameter o is null.
     */
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
  if (!obs.contains(o)) {
      obs.addElement(o);
  }
    }
 
    /**
     * Deletes an observer from the set of observers of this object. 
     *
     * @param   o   the observer to be deleted.
     */
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }
 
    /**
     * If this object has changed, as indicated by the 
     * <code>hasChanged</code> method, then notify all of its observers 
     * and then call the <code>clearChanged</code> method to 
     * indicate that this object has no longer changed. 
     * <p>
     * Each observer has its <code>update</code> method called with two
     * arguments: this observable object and <code>null</code>. In other 
     * words, this method is equivalent to:
     * <blockquote><tt>
     * notifyObservers(null)</tt></blockquote>
     *
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#hasChanged()
     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    public void notifyObservers() {
  notifyObservers(null);
    }
 
    /**
     * If this object has changed, as indicated by the 
     * <code>hasChanged</code> method, then notify all of its observers 
     * and then call the <code>clearChanged</code> method to indicate 
     * that this object has no longer changed. 
     * <p>
     * Each observer has its <code>update</code> method called with two
     * arguments: this observable object and the <code>arg</code> argument.
     *
     * @param   arg   any object.
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#hasChanged()
     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    public void notifyObservers(Object arg) {
  /*
         * a temporary array buffer, used as a snapshot of the state of
         * current Observers.
         */
        Object[] arrLocal;
 
  synchronized (this) {
      /* We don't want the Observer doing callbacks into
       * arbitrary code while holding its own Monitor.
       * The code where we extract each Observable from 
       * the Vector and store the state of the Observer
       * needs synchronization, but notifying observers
       * does not (should not).  The worst result of any 
       * potential race-condition here is that:
       * 1) a newly-added Observer will miss a
       *   notification in progress
       * 2) a recently unregistered Observer will be
       *   wrongly notified when it doesn't care
       */
      if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
 
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }
 
    /**
     * Clears the observer list so that this object no longer has any observers.
     */
    public synchronized void deleteObservers() {
  obs.removeAllElements();
    }
 
    /**
     * Marks this <tt>Observable</tt> object as having been changed; the 
     * <tt>hasChanged</tt> method will now return <tt>true</tt>.
     */
    protected synchronized void setChanged() {
  changed = true;
    }
 
    /**
     * Indicates that this object has no longer changed, or that it has 
     * already notified all of its observers of its most recent change, 
     * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>. 
     * This method is called automatically by the 
     * <code>notifyObservers</code> methods. 
     *
     * @see     java.util.Observable#notifyObservers()
     * @see     java.util.Observable#notifyObservers(java.lang.Object)
     */
    protected synchronized void clearChanged() {
  changed = false;
    }
 
    /**
     * Tests if this object has changed. 
     *
     * @return  <code>true</code> if and only if the <code>setChanged</code> 
     *          method has been called more recently than the 
     *          <code>clearChanged</code> method on this object; 
     *          <code>false</code> otherwise.
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#setChanged()
     */
    public synchronized boolean hasChanged() {
  return changed;
    }
 
    /**
     * Returns the number of observers of this <tt>Observable</tt> object.
     *
     * @return  the number of observers of this object.
     */
    public synchronized int countObservers() {
  return obs.size();
    }
}


caterpillar edited on 2013-04-07 16:03
reply to postreply to post
良葛格學習筆記
話題樹型展開
人氣 標題 作者 字數 發文時間
17093 [精華] Design Patterns 入門 - 觀察者(Observer) caterpillar 8633 2003-12-25 23:53
14939 Re:Design Patterns - 觀察者(Observer) popcorny 202 2003-12-29 22:02
15739 Re:Design Patterns - 觀察者(Observer) caterpillar 384 2003-12-29 23:21
14656 Re:Design Patterns - 觀察者(Observer) popcorny 156 2003-12-29 22:08
14736 Re:Design Patterns - 觀察者(Observer) caterpillar 549 2003-12-29 23:29
15082 Re:Design Patterns - 觀察者(Observer) popcorny 530 2003-12-30 00:56
11521 Re:Design Patterns 入門 - 觀察者(Observer) GuanChih 187 2006-02-10 10:37
13509 Re:Design Patterns 入門 - 觀察者(Observer) tempo 404 2006-02-10 18:20
» JWorld@TW »  Software Design » GoF

reply to postflat modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8