java observer模式_Java观察者模式(Observer)详解及应用
Java觀察者模式(Observer)詳解及應(yīng)用
(2011-12-15 14:03:30)
標(biāo)簽:
雜談
Java觀察者模式(Observer)詳解及應(yīng)用
由于網(wǎng)站帶有弱sns功能,因此需要設(shè)計(jì)關(guān)注和被關(guān)注的消息或是動(dòng)作通知,那么將這個(gè)需求抽象出來的時(shí)候就會(huì)發(fā)現(xiàn)正好符合java中
訂閱者模式,我還是喜歡叫觀察著模式,具體網(wǎng)站的實(shí)現(xiàn)代碼就不寫了,寫一個(gè)簡單的例子大家了解下即可
一、概述
Java的設(shè)計(jì)模式很多,觀察者模式被稱為是模式中的皇后,而且Java
jdk也對(duì)它做了實(shí)現(xiàn),可見該設(shè)計(jì)模式的重要位置。在圖形化設(shè)計(jì)的軟件中,為了實(shí)現(xiàn)視圖和事件處理的分離,大多都采用了Observer模式,比如Java的Swing,Flex的ActionScript等。在現(xiàn)實(shí)的應(yīng)用系統(tǒng)中也有好多應(yīng)用,比如像當(dāng)當(dāng)網(wǎng)、京東商城一類的電子商務(wù)網(wǎng)站,如果你對(duì)某件商品比較關(guān)注,可以放到收藏架,那么當(dāng)該商品降價(jià)時(shí),系統(tǒng)給您發(fā)送手機(jī)短信或郵件。這就是觀察者模式的一個(gè)典型應(yīng)用,商品是被觀察者,有的叫主體;關(guān)注該商品的客戶就是觀察者。下面的一個(gè)事例將模擬這個(gè)應(yīng)用。
GoF說道:Observer模式的意圖是“定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新”。從這段話里我們可以得到兩個(gè)信息,如下:
1, 觀察者(具體執(zhí)行操作的對(duì)象,有多個(gè))
2, 被觀察者(顧名思義是被觀察的對(duì)象,如果該對(duì)象發(fā)生某些變化則通知觀察者執(zhí)行對(duì)應(yīng)的操)
二、jdk中觀察者模式解析
在java的util包中實(shí)現(xiàn)了該設(shè)計(jì)模式的框架,大部分應(yīng)用都可以直接用它,當(dāng)然了你也可以自己實(shí)現(xiàn)它,實(shí)際上就是一個(gè)被觀察者的抽象類和一個(gè)觀察者接口。我們先看一下jdk是如何實(shí)現(xiàn)的。被觀察者的抽象類java.util.Observable
package java.util;
public class Observable {
private boolean changed = false;
private Vector obs;
//創(chuàng)建被觀察者時(shí)就創(chuàng)建一個(gè)它持有的觀察者列表,注意,這個(gè)列表是需要同步的。
public Observable() {
obs = new Vector();
}
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
當(dāng)我們自己的被觀察者繼承這個(gè)Observable類是,我們就自動(dòng)的獲取到被觀察者的一切條件了。很方便是不是,這也是為什么sun要把Observable放到j(luò)ava.util包中的原因,就是為了方便開發(fā)者。
下面我們再看一下觀察者的接口java.util.Observer
package java.util;
public interface Observer {
void update(Observable o, Object arg);
}
接口中就只有一個(gè)方法,update,方法中有兩個(gè)參數(shù),Observable和一個(gè)object,第一個(gè)參數(shù)就是被觀察的對(duì)象,而第二個(gè)參數(shù)就得看業(yè)務(wù)需求了,需要什么就傳進(jìn)去什么。我們自己的觀察者類必須實(shí)現(xiàn)這個(gè)方法,這樣在被觀察者調(diào)用notifyObservers操作時(shí)被觀察者所持有的所有觀察者都會(huì)執(zhí)行update操作了.
三、觀察者模式應(yīng)用
下面是一個(gè)book對(duì)象,它是一個(gè)被觀察者,所以要繼承Observable。
import java.util.Observable;
public class Book extends Observable {
private String name = "";
private double price = 0.0;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
//當(dāng)書的價(jià)格修改時(shí)調(diào)用該方法
public void modifyPrice(Book b) {
//調(diào)用父類的方法,改變被觀察者的狀態(tài)
setChanged();
//通知客戶該書已降價(jià)
notifyObservers(b);
}
}
下面是觀察者對(duì)象,表示顧客的電子郵件,它實(shí)現(xiàn)了Observer接口。
import java.util.Observable;
import java.util.Observer;
public class BuyerEmail implements Observer {
private String buyerId = "";
private String email = "";
public String getBuyerId() {
return buyerId;
}
public void setBuyerId(String buyerId) {
this.buyerId = buyerId;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
//該方法會(huì)被“被觀察者的父類”既Observable調(diào)用
public void update(Observable o, Object arg) {
//這里做具體發(fā)電子郵件的操作
Book b = (Book)arg;
System.out.println("給顧客的發(fā)電子郵件:"+b.getName()+"降價(jià)了,目前價(jià)格為:"+b.getPrice());
}
}
下面是另一個(gè)觀察者對(duì)象,表示顧客的手機(jī),同樣需要繼承Observer接口
import java.util.Observable;
import java.util.Observer;
public class BuyerMobileMessage implements Observer {
private String buyerId = "";
private String mobileNo = "";
public String getBuyerId() {
return buyerId;
}
public void setBuyerId(String buyerId) {
this.buyerId = buyerId;
}
public String getMobileNo() {
return mobileNo;
}
public void setMobileNo(String mobileNo) {
this.mobileNo = mobileNo;
}
public void update(Observable o, Object arg) {
// TODO Auto-generated method stub
Book b = (Book)arg;
System.out.println("給顧客的發(fā)手機(jī)短信:"+b.getName()+"降價(jià)了,目前價(jià)格為:"+b.getPrice());
}
}
下面是調(diào)用類:
public class MainApp {
public static void main(String args[])
{
Book b1 = new Book();
b1.setName("<>");
b1.setPrice(45.00);//假設(shè)原價(jià)是60,現(xiàn)在是降價(jià)促銷
//下面的觀察者在實(shí)際的應(yīng)用中可以從數(shù)據(jù)庫或文件中讀取
BuyerMobileMessage bm = new BuyerMobileMessage();
bm.setBuyerId("001");
bm.setMobileNo("13810500085");
BuyerEmail be = new BuyerEmail();
be.setBuyerId("001");
be.setEmail("dobodo@163.com");
//增加觀察者,在實(shí)際應(yīng)用中就是那些人對(duì)該書做了關(guān)注
b1.addObserver(bm);
b1.addObserver(be);
b1.modifyPrice(b1);
}
}
輸出:
給顧客的發(fā)電子郵件:<>降價(jià)了,目前價(jià)格為:45.0
給顧客的發(fā)手機(jī)短信:<>降價(jià)了,目前價(jià)格為:45.0
不知道上面的例子你看懂了沒有,觀察者模式實(shí)際上沒什么高深的東西,就是運(yùn)用了java的繼承和接口,在被觀察者的抽象類里設(shè)置一個(gè)狀態(tài)標(biāo)志,通過該標(biāo)志判斷是否通知觀察者對(duì)象。在學(xué)習(xí)該模式的同時(shí),我們更應(yīng)該學(xué)習(xí)java的繼承和接口的靈活應(yīng)用,其實(shí)所有的設(shè)計(jì)模式都是繼承、接口、多態(tài)的靈活應(yīng)用
分享:
喜歡
0
贈(zèng)金筆
加載中,請稍候......
評(píng)論加載中,請稍候...
發(fā)評(píng)論
登錄名: 密碼: 找回密碼 注冊記住登錄狀態(tài)
昵???稱:
評(píng)論并轉(zhuǎn)載此博文
發(fā)評(píng)論
以上網(wǎng)友發(fā)言只代表其個(gè)人觀點(diǎn),不代表新浪網(wǎng)的觀點(diǎn)或立場。
總結(jié)
以上是生活随笔為你收集整理的java observer模式_Java观察者模式(Observer)详解及应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java win10 通知,如何使用Ja
- 下一篇: Ajax解析laravelJSON,3分