Java Q&A: 使用Observer模式 (轉)
Q&A: 使用Observer
A:我想在自己的Java中使用Observer模式。基於此,能否提供某些示例程式碼來演示如何去做?
Q:正如面向有助於程式碼複用一樣,設計模式可以促進設計複用。確實,設計模式可以讓你複用那些正確的、成熟的設計。但近來,批評設計模式的越來越多。批評者指出,缺乏的開發者會很容易地掉進 "模式陷阱" 之中。
模式陷阱讓缺乏經驗的開發者迷失了方向。因而,他們在處理問題時不是去尋找可能存在的最好方案,而把最終目標集中在儘可能地實現更多的設計模式之上。在一些人看來,使用設計模式好象必然會帶來良好的設計。按照這個邏輯,只要大量使用設計模式,就必然為你產生一個優秀的設計!然而現實中,這一觀點卻導致出許多毫無意義的設計--即使這個設計採用了多個設計模式。看來很遺憾,設計模式並不能保證良好的設計。
要想在設計中正確地運用一個設計模式,必須確保三個條件:
1. 弄清你的問題
2. 瞭解這個模式
3. 理解這個模式如何解決你的問題
首先,最重要的是條件1。如果不能完全地弄清你要解決的問題,何談運用模式?
還要知道條件2:必須完全瞭解你想運用的模式。不瞭解它怎麼能運用它?更重要的是,連一個模式做什麼都不知道,又如何想到去用它?
最後一點,如果你不能清楚地說出模式將怎樣解決你的問題(為什麼這個模式合適),那還是放棄它。僅僅為了用模式本身而去用它,就會掉進模式陷阱之中。
我並不是在說提這個問題的讀者也一定會掉進模式陷阱。但從提問的表達上來看,它很容易誤導一些開發者去理解設計模式。我對這個提問的理解是,這位讀者應該清楚自己需要解決的問題,也瞭解Observer模式,他/她只是不知道如何用Java來實現。
在給出一個Java示例之前,為了有助於其他讀者也能理解,先簡要介紹一下Observer模式。
簡單來說,Observer模式讓一個物件(觀察者,Observer)去監視另一個物件(目標,Subject);它使得目標和觀察者之間建立一種 "釋出--訂閱"(publish-subscribe )的關係。透過Observer模式,觀察者可以向目標登記,表明自己要從目標接收事件。目標需要向觀察者通知事件時,只是簡單地將事件發給每一個觀察者。
例如,有一個基於某種資料模型的電子表格。只要資料模型發生變化,電子表格就需要表格單元以及內嵌的圖表。這個例子中,目標是資料模型,觀察者是表格單元和圖表。當觀察者接收到資料模型已經變化的通知時,它們就更新自己。
Observer模式的好處是:它解除了觀察者和目標之間的耦合關係。目標不需要知道它的觀察者的任何資訊。相反,目標只是允許觀察者訂閱事件。當目標產生一個事件時,它簡單地將事件傳給每一個觀察者。
看看下面的Java示例:
public interface Subject {
public void addObserver( Observer o );
public void removeObserver( Observer o );
}
上面的程式碼中,Subject介面定義了兩個方法(method),每個Subject都必須實現它們,以使Observer可以在Subject中增加或刪除自身。
public interface Observer {
public void update( Subject o );
}
Observer介面(如上)列出了一個方法(method),每個Observer都必須實現它,以使Subject可以傳送更新訊息給Observer。
下面看看Subject的一個簡單的實現--IntegerDataBag:
import java.util.ArrayList;
import java.util.Iterator;
public class IntegerDataBag implements Subject {
private ArrayList list = new ArrayList();
private ArrayList observers = new ArrayList();
public void add( Integer i ) {
list.add( i );
notifyObservers();
}
public Iterator iterator() {
return list.iterator();
}
public Integer remove( int index ) {
if( index < list.size() ) {
Integer i = (Integer) list.remove( index );
notifyObservers();
return i;
}
return null;
}
public void addObserver( Observer o ) {
observers.add( o );
}
public void removeObserver( Observer o ) {
observers.remove( o );
}
private void notifyObservers() {
// l through and notify each observer
Iterator i = observers.iterator();
while( i.hasNext() ) {
Observer o = ( Observer ) i.next();
o.update( this );
}
}
}
IntegerDataBag適用於使用Integer的場合。IntegerDataBag也允許Observer增加和刪除它們自身。
再看看兩個Observer的實現--IntegerAdder和IntegerPrinter:
import java.util.Iterator;
public class IntegerAdder implements Observer {
private IntegerDataBag bag;
public IntegerAdder( IntegerDataBag bag ) {
this.bag = bag;
bag.addObserver( this );
}
public void update( Subject o ) {
if( o == bag ) {
System.out.println( "The contents of the IntegerDataBag have changed." );
int counter = 0;
Iterator i = bag.iterator();
while( i.hasNext() ) {
Integer integer = ( Integer ) i.next();
counter+=integer.intValue();
}
System.out.println( "The new sum of the integers is: " + counter );
}
}
}
import java.util.Iterator;
public class IntegerPrinter implements Observer {
private IntegerDataBag bag;
public IntegerPrinter( IntegerDataBag bag ) {
this.bag = bag;
bag.addObserver( this );
}
public void update( Subject o ) {
if( o == bag ) {
System.out.println( "The contents of the IntegerDataBag have changed." );
System.out.println( "The new contents of the IntegerDataBag contains:" );
Iterator i = bag.iterator();
while( i.hasNext() ) {
System.out.println( i.next() );
}
}
}
}
IntegerAdder和IntegerPrinter將自己作為觀察者增加到IntegerDataBag。當IntegerAdder接收到一條更新訊息時,它先統計bag中的總數,然後顯示結果。同樣,當IntegerPrinter接收到一條更新訊息時,它列印出bag中的Interger。
下面是一個簡單的main(),它使用了上面的幾個類:
public class {
public static void main( String [] args ) {
Integer i1 = new Integer( 1 ); Integer i2 = new Integer( 2 );
Integer i3 = new Integer( 3 ); Integer i4 = new Integer( 4 );
Integer i5 = new Integer( 5 ); Integer i6 = new Integer( 6 );
Integer i7 = new Integer( 7 ); Integer i8 = new Integer( 8 );
Integer i9 = new Integer( 9 );
IntegerDataBag bag = new IntegerDataBag();
bag.add( i1 ); bag.add( i2 ); bag.add( i3 ); bag.add( i4 );
bag.add( i5 ); bag.add( i6 ); bag.add( i7 ); bag.add( i8 );
IntegerAdder adder = new IntegerAdder( bag );
IntegerPrinter printer = new IntegerPrinter( bag );
// adder and printer add themselves to the bag
System.out.println( "About to add another integer to the bag:" );
bag.add( i9 );
System.out.println("");
System.out.println("About to remove an integer from the bag:");
bag.remove( 0 );
}
}
執行main,你將看到:
c:javaworldjava Driver
About to add another integer to the bag:
The contents of the IntegerDataBag have changed.
The new sum of the intergers is: 45
The contents of the IntegerDataBag have changed.
The new contents of the IntegerDataBag contains:
1
2
3
4
5
6
7
8
9
About to remove an integer from the bag:
The contents of the IntegerDataBag have changed.
The new sum of the intergers is: 44
The contents of the IntegerDataBag have changed.
The new contents of the IntegerDataBag contains:
2
3
4
5
6
7
8
9
IntegerDataBag/IntegerAdder/IntegerPrinter是應用Observer模式的一個很簡單的例子。Java本身有大量使用Observer模式的例子:AWT/事件模型,還有java.util.Observer和java.util.Observable介面等,都是很好的例子。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990768/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java Q&A: 使用Factory Method模式 (轉)Java模式
- Java Q&A: 使用Singleton模式?給我一個理由先! (轉)Java模式
- Java中使用Observer介面和Observable類實踐Observer觀察者模式JavaServer模式
- Java:應用Observer介面實踐Observer模式薦JavaServer模式
- 設計模式----Observer模式設計模式Server
- 應用Observer介面實踐Observer模式Server模式
- Java23種設計模式【22】----》觀察者模式(Observer)Java設計模式Server
- 設計模式:觀察者模式(observer)設計模式Server
- observer-觀察者模式Server模式
- Observer模式的問題Server模式
- Visitor模式和Observer觀察者模式模式Server
- 設計模式應用之Observer模式(2)設計模式Server
- 設計模式應用之Observer模式(1)設計模式Server
- 看了設計模式之Observer設計模式Server
- banq 你好,請教Observer模式Server模式
- 設計模式之觀察者模式(Observer Pattern)設計模式Server
- 【 應用以及剖析】之 java.util.Observer 觀察者模式實現JavaServer模式
- 人人都會設計模式—觀察者模式–Observer設計模式Server
- 人人都會設計模式---觀察者模式--Observer設計模式Server
- C#設計模式系列:觀察者模式(Observer)C#設計模式Server
- Head First 設計模式(2)---觀察者(Observer)模式設計模式Server
- 設計模式-- 觀察者模式Observer(物件行為型)設計模式Server物件
- C#設計模式(17)——觀察者模式(Observer Pattern)C#設計模式Server
- Java的秘密:使用全螢幕模式 (轉)Java模式
- 設計模式(三)觀察者模式Observer(釋出訂閱)設計模式Server
- 談 C++17 裡的 Observer 模式 - 補C++Server模式
- 原生實現的觀察者模式(Observer Model)模式Server
- 談 C++17 裡的 Observer 模式 - 3C++Server模式
- 重構到觀察者模式 Refactor to Observer Pattern模式Server
- 剪貼簿中的觀察者(Observer)模式Server模式
- Observer Design Pattern in C#! (轉)ServerC#
- 談 C++17 裡的 Observer 模式 - 4 - 訊號槽模式C++Server模式
- (轉)*Socket TIME_WAIT 問題Q&AAI
- Javaweb Q&AJavaWeb
- Observer Pattern - An Enterprise JavaBean Implementation (轉)ServerJavaBean
- Laravel 中模型事件 Observer 的使用Laravel模型事件Server
- 實現觀察者模式(Observer Pattern)的2種方式模式Server
- Banq:看了你的設計模式:Observer,有些疑問設計模式Server