設計模式之Observer

觀察者模式可以參考郵件訂閱的例子

郵件訂閱設計到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動作.

在商品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;
  private float price;

  public String getName(){ return name;}
  public void setName(String name){
   this.name=name;
  //設置變化點
   setChanged();
   notifyObservers(name);

  }   

  public float getPrice(){ return price;}
  public void setPrice(float price){
   this.price=price;
  //設置變化點
   setChanged();
   notifyObservers(new Float(price));

  }

  //以下可以是數據庫更新 插入命令.
  public void saveToDb(){
  .....................

}


我們注意到,在product類中 的setXXX方法中,我們設置了 notify(通知)方法, 當Jsp表單調用setXXX(如何調用見我的另外一篇文章),實際上就觸發了notisfyObservers方法,這將通知相應觀察者應該采取行動了.

下面看看這些觀察者的代碼,他們究竟采取了什么行動:

//觀察者NameObserver主要用來對產品名稱(name)進行觀察的
public class NameObserver implements Observer{

  private String name=null;

  public void update(Observable obj,Object arg){

    if (arg instanceof String){

     name=(String)arg;
     //產品名稱改變值在name中
     System.out.println("NameObserver :name changet to "+name);

    }

  }

}

//觀察者PriceObserver主要用來對產品價格(price)進行觀察的
public class PriceObserver implements Observer{

  private float price=0;

  public void update(Observable obj,Object arg){

    if (arg instanceof Float){

     price=((Float)arg).floatValue();
  
     System.out.println("PriceObserver :price changet to "+price);

    }

  }

}


Jsp中我們可以來正式執行這段觀察者程序:

<jsp:useBean id="product" scope="session" class="Product" />
<jsp:setProperty name="product" property="*" />

<jsp:useBean id="nameobs" scope="session" class="NameObserver" />
<jsp:setProperty name="product" property="*" />

<jsp:useBean id="priceobs" scope="session" class="PriceObserver" />
<jsp:setProperty name="product" property="*" />

<%

if (request.getParameter("save")!=null)
{
  product.saveToDb();


  out.println("產品數據變動 保存! 并已經自動通知客戶");

}else{

  //加入觀察者
  product.addObserver(nameobs);

  product.addObserver(priceobs);

%>

  //request.getRequestURI()是產生本jsp的程序名,就是自己調用自己
  <form action="<%=request.getRequestURI()%>" method=post>

  <input type=hidden name="save" value="1">
  產品名稱:<input type=text name="name" >
  產品價格:<input type=text name="price">
  <input type=submit>

  </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();

NameObserver nameobs=new NameObserver();
PriceObserver priceobs=new PriceObserver();

//加入觀察者
product.addObserver(nameobs);
product.addObserver(priceobs);

product.setName("橘子紅了");
product.setPrice(9.22f);

  }

}

?

?

?

你會在發現下面信息::

NameObserver :name changet to 橘子紅了

PriceObserver :price changet to 9.22

這說明觀察者在行動了.!!

?

轉載于:https://www.cnblogs.com/javaTest/archive/2010/04/18/2589446.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379266.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379266.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379266.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

編寫一個程序,計算|X-Y|的值,并將結果存入RESULT單元中,其中X和Y都為帶符號字數據。

編寫一個程序&#xff0c;計算|X-Y|的值&#xff0c;并將結果存入RESULT單元中&#xff0c;其中X和Y都為帶符號字數據。 P154 例4.11 匯編思路:DATA段定義X、Y、RESULE分別用于存放隨機數、存放隨機數、存放最后計算結果。STACK段定義100DB大小的堆棧段運算存儲空間。將AX獲取…

java timezone_Java TimeZone inDaylightTime()方法及示例

java timezoneTimeZone類inDaylightTime()方法 (TimeZone Class inDaylightTime() method) inDaylightTime() method is available in java.util package. inDaylightTime()方法在java.util包中可用。 inDaylightTime() method is used to check whether the given date (d) is…

這幾天好像博客登不上去 什么情況

這幾天好像博客登不上去 什么情況 我多年的心情記錄啊 還以為關掉了 。。。。。。。 今天很生氣&#xff0c;麻痹 轉載于:https://www.cnblogs.com/cloud/archive/2010/04/25/1720744.html

雙向鏈表(代碼、分析、匯編)

目錄&#xff1a;代碼&#xff1a;分析&#xff1a;匯編&#xff1a;代碼&#xff1a; DLinkList.h #ifndef _DLINKLIST_H_ #define _DLINKLIST_H_typedef void DLinkList; typedef struct _tag_DLinkListNode DLinkListNode; struct _tag_DLinkListNode {DLinkListNode* nex…

[道理]關于人生的,很不錯!

[道理]關于人生的&#xff0c;很不錯&#xff01; 心理學課上&#xff0c;周正教授正在授課&#xff1a;“上次下課時&#xff0c;一個男孩子遞了張紙條&#xff1a;我是個比較內向的人&#xff0c;又沒什么特長&#xff0c;不會踢足球&#xff0c;不會打籃球……唯一的愛好是寫…

變量和簡單數據類型(一)

1&#xff0c;title()方法 將字符串中的每個單詞的首字符大寫 2&#xff0c;upper()方法 將字符串的所有字母大寫 3&#xff0c;lower()方法 將字符串的所有字母小寫 name "beyond Sq" print(name.title()) print(name.upper()) print(name.lower())調用方式&…

long類型20位示例_Java Long類lowerOneBit()方法與示例

long類型20位示例長類lowerOneBit()方法 (Long class lowestOneBit() method) lowestOneBit() method is available in java.lang package. minimumOneBit()方法在java.lang包中可用。 lowestOneBit() method is used to find at most only single 1’s bit from the rightmost…

VS2010安裝、啟動都挺快的,真不錯

截圖留念&#xff0c;里面的源碼是《把脈VC》一書的示例工程。 轉載于:https://www.cnblogs.com/silentmj/archive/2010/04/29/1723940.html

hdu 1712

地址&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1712 題意&#xff1a;復習課程&#xff0c;n們課&#xff0c;有m天復習&#xff0c;a[i][j]代表用j天來復習第i門課的收獲。。&#xff08;這里居然可能用的天數多而收獲更少……囧&#xff09; mark&#xff1a;第…

Python中的or和and運算符的使用

通俗來講 or&#xff1a;找真值&#xff0c;若第一個為真則返回該值&#xff1b;若全都不為真&#xff0c;則返回最后一個假值 and&#xff1a;找假值&#xff0c;若第一個為假則返回該值&#xff1b;若全都不為假&#xff0c;則返回最后一個真值 牢記這兩句話&#xff01;&…

棧-線性表(代碼、分析、匯編)

目錄&#xff1a;代碼&#xff1a;分析&#xff1a;匯編&#xff1a;代碼&#xff1a; LinkList.h #ifndef _LINKLIST_H_ #define _LINKLIST_H_typedef void LinkList; //定義鏈表類型 typedef struct _tag_LinkListNode LinkListNode;//定義鏈表節點類型 struct _tag_LinkL…

Java IdentityHashMap isEmpty()方法與示例

IdentityHashMap類isEmpty()方法 (IdentityHashMap Class isEmpty() method) isEmpty() method is available in java.util package. isEmpty()方法在java.util包中可用。 isEmpty() method is used to check whether this IdentityHashMap is "empty" or "not …

datatable序列化為string

代碼 privatestaticstringSerializeDataTableXml(DataTable pDt){ //序列化DataTableStringBuilder sb newStringBuilder(); XmlWriter writer XmlWriter.Create(sb); XmlSerializer serializer newXmlSerializer(typeof(DataTable)); serializer.Serialize(writer, pD…

C#常用輸出格式

輸出方法Console. WriteLine( ) Console. WriteLine()方法將數據輸出到屏幕并加上一個回車換行符(若不加回車換行 符&#xff0c;可用Console. Write()方法)。 該方法類似于C語言中的printf()函數, 可以采用“{N[,M][:格式化字符串]}”的形式格式化輸出字符串,其中的參數含義如…

棧-順序表(代碼、分析、匯編)

目錄&#xff1a;代碼&#xff1a;分析&#xff1a;匯編&#xff1a;代碼&#xff1a; SeqList.h #ifndef _SEQLIST_H_ #define _SEQLIST_H_typedef void SeqList;//定義順序表類型 typedef void SeqListNode;//定義順序表節點類型SeqList* SeqList_Create(int capacity);voi…

sqlserver 數據庫日志文件過大的問題

USE[master] GO ALTER DATABASE 【數據庫】 SET RECOVERY SIMPLE WITH NO_WAIT GO ALTER DATABASE 【數據庫】 SET RECOVERY SIMPLE --簡單模式 GO USE 【數據庫】 GO DBCC SHRINKFILE (N【數據庫日志文件名&#xff08;如&#xff1a;msdb_log&#xff09;】 , 11, TRUNCATE…

SQl Server存儲過程基礎

一、存儲過程的概念 存儲過程是SQL語句和可選控制流語句的預編譯集合&#xff0c;存儲在數據庫中&#xff0c;可由應用程序通過一個調用執行&#xff0c;而且允許用戶聲明變量、有條件執行以及其他強大的編程功能。 在SQL Server中存儲過程分為兩類&#xff1a;即系統提供的存儲…

isinfinite_Java Double類isInfinite()方法與示例

isinfinite雙類isInfinite()方法 (Double class isInfinite() method) isInfinite() method is available in java.lang package. isInfinite()方法在java.lang包中可用。 isInfinite() method is used to check infinity (i.e. either positive infinity or negative infinity…

MySql學習(一)

SQL語句的分類&#xff1a;DDL&#xff08;數據定義語言&#xff09;、DML&#xff08;數據操作語言&#xff09;、DCL&#xff08;數據控制語句&#xff09;MySql的命令語句以&#xff1b;或\g結束建庫&#xff1a;Create database name;建表&#xff1a;Create tablle name;選…

C盤爆紅的解決辦法

方法一&#xff1a;開始—>搜索—>cleanmgr—>磁盤清理—>選擇你所需要清理的磁盤即可 方法二&#xff1a;我的電腦右擊—>管理—>磁盤管理—>右鍵選擇你要壓縮的磁盤—>壓縮卷—>輸入壓縮空間量—>壓縮—>右鍵 拓展卷—>下一步—>輸入…