觀察者模式可以參考郵件訂閱的例子
郵件訂閱設計到2個主要角色,一個是訂閱者(觀察者),一個是發布者
?
發布者可以擁有一個觀察者的集合,可以添加,刪除觀察者,當發布者發布一個新的消息時,要郵件通知觀察者集合中的每一個。
所以,發布者實現的接口至少應具備三個方法,即注冊觀察者,注銷觀察者,通知觀察者。
?
通知有兩種方式,一種是推(push),一種是拉(pull).
推,即發布者通過調用觀察者提供的接口,來告之所有的變動(比如新增一個消息),主動推送給觀察者。
拉,及觀察者可以按需提取所要接受的數據,而不是全盤接受,主要體現在程序自己主動調用觀察者的傳值接口,而區別于推由發布者來調用,此時,需要這個借口中的參數包含發布者對象,讓程序知道掃描變動來自于哪個發布者。
?
JDK中內置了觀察者模式,位于java.util包中,一個接口Observer,一個類Observable,將這兩個類組合起來使用,既可以推,又可以拉。
一個普通的類,如果繼承了Observable,就成了一個發布者,實現了Observer接口,就成了觀察者。
JDK中的觀察者模式有一個弊端,就是發布者需要繼承一個類,而不是實現一個接口,如果需要成為發布者的類已經集成了一個類,就不能再繼承Observable了。這時候,就需要自己來設計一種觀察者模式了。
?
JDK 中Swing包中,大量運用了觀察者模式,所有的組件都繼承了JComponent,這就是一個發布者,它里面包含一個監聽器的集合:EventListenerList,用戶可以自定義一個監聽器,然后添加到一個組件中的時候,該組件就會把這個監聽器注冊到 EventListenerList中,相當于添加了一個發布者,當用戶對組件做出反映時,所有的監聽器(發布者)都會收到信息并作出反應。
?
********************************************************
?
Java深入到一定程度,就不可避免的碰到設計模式(design pattern)這一概念,了解設計模式,將使自己對java中的接口或抽象類應用有更深的理解.設計模式在java的中型系統中應用廣泛,遵循一定的編程模式,才能使自己的代碼便于理解,易于交流,Observer(觀察者)模式是比較常用的一個模式,尤其在界面設計中應用廣泛,而本站所關注的是Java在電子商務系統中應用,因此想從電子商務實例中分析Observer的應用.
雖然網上商店形式多樣,每個站點有自己的特色,但也有其一般的共性,單就"商品的變化,以便及時通知訂戶"這一點,是很多網上商店共有的模式,這一模式類似Observer patern觀察者模式.
具體的說,如果網上商店中商品在名稱 價格等方面有變化,如果系統能自動通知會員,將是網上商店區別傳統商店的一大特色.這就需要在商品product中加入Observer這樣角色,以便product細節發生變化時,Observer能自動觀察到這種變化,并能進行及時的update或notify動作.
Java的API還為為我們提供現成的Observer接口Java.util.Observer.我們只要直接使用它就可以.
我們必須extends Java.util.Observer才能真正使用它:
1.提供Add/Delete observer的方法;
2.提供通知(notisfy) 所有observer的方法;
//產品類 可供Jsp直接使用UseBean調用 該類主要執行產品數據庫插入 更新 public class product extends Observable{ private String name; public String getName(){ return name;} } public float getPrice(){ return price;} } } |
我們注意到,在product類中 的setXXX方法中,我們設置了 notify(通知)方法, 當Jsp表單調用setXXX(如何調用見我的另外一篇文章),實際上就觸發了notisfyObservers方法,這將通知相應觀察者應該采取行動了.
下面看看這些觀察者的代碼,他們究竟采取了什么行動:
//觀察者NameObserver主要用來對產品名稱(name)進行觀察的 private String name=null; public void update(Observable obj,Object arg){ name=(String)arg; } } } //觀察者PriceObserver主要用來對產品價格(price)進行觀察的 private float price=0; public void update(Observable obj,Object arg){ price=((Float)arg).floatValue(); } } } |
Jsp中我們可以來正式執行這段觀察者程序:
<jsp:useBean id="product" scope="session" class="Product" /> <jsp:useBean id="nameobs" scope="session" class="NameObserver" /> <jsp:useBean id="priceobs" scope="session" class="PriceObserver" /> <% }else{ %> //request.getRequestURI()是產生本jsp的程序名,就是自己調用自己 <input type=hidden name="save" value="1"> </form> <% %> ? ? ? |
執行改Jsp程序,會出現一個表單錄入界面, 需要輸入產品名稱 產品價格, 點按Submit后,還是執行該jsp的
if (request.getParameter("save")!=null)之間的代碼.
由于這里使用了數據javabeans的自動賦值概念,實際程序自動執行了setName setPrice語句.你會在服務器控制臺中發現下面信息::
NameObserver :name changet to ?????(Jsp表單中輸入的產品名稱)
PriceObserver :price changet to ???(Jsp表單中輸入的產品價格);
這說明觀察者已經在行動了.!!
同時你會在執行jsp的瀏覽器端得到信息:
產品數據變動 保存! 并已經自動通知客戶
上文由于使用jsp概念,隱含很多自動動作,現將調用觀察者的Java代碼寫如下:
? public class Test { public static void main(String args[]){ Product product=new Product(); //加入觀察者 product.setName("橘子紅了"); } } ? ? ? |
你會在發現下面信息::
NameObserver :name changet to 橘子紅了
PriceObserver :price changet to 9.22
這說明觀察者在行動了.!!
?