最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java觀察者設(shè)計模式(Observable和Observer)

 更新時間:2015年12月09日 14:46:06   投稿:mrr  
這篇文章主要介紹了 Java觀察者設(shè)計模式(Observable和Observer)的相關(guān)資料,需要的朋友可以參考下

觀察者模式定義了一種一對多的依賴關(guān)系,讓多個觀察者對象同時監(jiān)聽某一個主題對象。

這個主題對象在狀態(tài)上發(fā)生變化時,會通知所有觀察者對象,讓它們能夠自動更新自己。

一、觀察者模式介紹

在Java中通過Observable類和Observer接口實現(xiàn)了觀察者模式。一個Observer對象監(jiān)視著一個Observable對象的變化,當(dāng)Observable對象發(fā)生變化時,Observer得到通知,就可以進(jìn)行相應(yīng)的工作。

如果畫面A是顯示數(shù)據(jù)庫里面的數(shù)據(jù),而畫面B修改了數(shù)據(jù)庫里面的數(shù)據(jù),那么這時候畫面A就要重新Load。這時候就可以用到觀察者模式

二、觀察者模式實現(xiàn)方法

java.util.Observable中有兩個方法對Observer特別重要

①setChanged()方法

/** 
* Sets the changed flag for this {@code Observable}. After calling 
* {@code setChanged()}, {@code hasChanged()} will return {@code true}. 
*/ 
protected void setChanged() { 
changed = true; 
} 
②notifyObservers()方法 / notifyObservers(Object data)方法
[java] view plaincopy
/** 
* If {@code hasChanged()} returns {@code true}, calls the {@code update()} 
* method for every observer in the list of observers using null as the 
* argument. Afterwards, calls {@code clearChanged()}. 
* <p> 
* Equivalent to calling {@code notifyObservers(null)}. 
*/ 
public void notifyObservers() { 
notifyObservers(null); 
} 
/** 
* If {@code hasChanged()} returns {@code true}, calls the {@code update()} 
* method for every Observer in the list of observers using the specified 
* argument. Afterwards calls {@code clearChanged()}. 
* 
* @param data 
* the argument passed to {@code update()}. 
*/ 
@SuppressWarnings("unchecked") 
public void notifyObservers(Object data) { 
int size = 0; 
Observer[] arrays = null; 
synchronized (this) { 
if (hasChanged()) { 
clearChanged(); 
size = observers.size(); 
arrays = new Observer[size]; 
observers.toArray(arrays); 
} 
} 
if (arrays != null) { 
for (Observer observer : arrays) { 
observer.update(this, data); 
} 
} 
} 

以上兩個方法十分重要

setChanged()方法 ——

用來設(shè)置一個內(nèi)部標(biāo)志位注明數(shù)據(jù)發(fā)生了變化
notifyObservers()方法 / notifyObservers(Object data)方法 ——
通知所有的Observer數(shù)據(jù)發(fā)生了變化,這時所有的Observer會自動調(diào)用復(fù)寫好的update(Observable observable, Object data)方法來做一些處理(比如說畫面數(shù)據(jù)的更新)。
我們可以看到通知Observer有兩個方法,一個無參,一個有參。那么這個參數(shù)有什么作用呢?
其中一個作用:現(xiàn)在我不想通知所有的Observer,而只想其中一個指定的Observer做一些處理,那么就可以傳一個參數(shù)作為ID,然后在所有的Observer中判斷,每個Observer判斷只有接收到底參數(shù)ID是屬于自己的才做一些處理。

當(dāng)然參數(shù)還有其他作用,我只是舉了個例子。

下面舉個例子加以說明:

import java.util.Observable; 
/** 
* 被觀察者類 
*/ 
public class SimpleObservable extends Observable 
{ 
private int data = 0; 
public int getData(){ 
return data; 
} 
public void setData(int i){ 
if(this.data != i) { 
this.data = i; 
setChanged(); 
//只有在setChange()被調(diào)用后,notifyObservers()才會去調(diào)用update(),否則什么都不干。 
notifyObservers(); 
} 
} 
} 

上面這個類是一個被觀察者類,它繼承了Observable類,表示這個類是可以被觀察的。
然后在setData()方法里面,也就是數(shù)據(jù)改變的地方,來調(diào)用Observable類的setChanged()方法和notifyObservers()方法,表示數(shù)據(jù)已改變并通知所有的Observer調(diào)用它們的update()方法做一些處理。

注意:只有在setChange()被調(diào)用后,notifyObservers()才會去調(diào)用update(),否則什么都不干。

/** 
* 觀察者類 
*/ 
public class SimpleObserver implements Observer 
{ 
public SimpleObserver(SimpleObservable simpleObservable){ 
simpleObservable.addObserver(this ); 
} 

public void update(Observable observable ,Object data){ // data為任意對象,用于傳遞參數(shù) 
System.out.println(“Data has changed to” + (SimpleObservable)observable.getData()); 
} 
} 

通過生成被觀察者(SimpleObservable類)的實例,來調(diào)用addObserver(this)方法讓觀察者(SimpleObserver類)達(dá)到觀察被觀察者(SimpleObservable類)的目的。
然后還要復(fù)寫update()方法,做數(shù)據(jù)改變后的一些處理。

下面可以寫一個簡單的測試類來測試一下

public class SimpleTest 
{ 
public static void main(String[] args){ 
SimpleObservable doc = new SimpleObservable (); 
SimpleObserver view = new SimpleObserver (doc); 
doc.setData(1); 
doc.setData(2); 
doc.setData(2); 
doc.setData(3); 
} 
} 

運行結(jié)果如下

Data has changed to 1
Data has changed to 2 //第二次setData(2)時由于沒有setChange,所以update沒被調(diào)用
Data has changed to 3

下面介紹一個Observable類的其他一些屬性和方法

屬性 ——

// observers是一個List,保存著所有要通知的observer。
List<Observer> observers = new ArrayList<Observer>();
// changed是一個boolean型標(biāo)志位,標(biāo)志著數(shù)據(jù)是否改變了。
boolean changed = false;

方法 ——

// 添加一個Observer到列表observers中 
public void addObserver(Observer observer) { 
if (observer == null) { 
throw new NullPointerException(); 
} 
synchronized (this) { 
if (!observers.contains(observer)) 
observers.add(observer); 
} 
} 
// 從列表observers中刪除一個observer 
public synchronized void deleteObserver(Observer observer) { 
observers.remove(observer); 
} 
// 清空列表observers 
public synchronized void deleteObservers() { 
observers.clear(); 
} 
// 返回列表observers中observer的個數(shù) 
public int countObservers() { 
return observers.size(); 
} 
// 重置數(shù)據(jù)改變標(biāo)志位為未改變 
protected void clearChanged() { 
changed = false; 
} 
// 將數(shù)據(jù)改變標(biāo)志位設(shè)置為改變 
protected void setChanged() { 
changed = true; 
} 
// 判斷標(biāo)志位的值 
public boolean hasChanged() { 
return changed; 
} 
// 通知所有observer(無參) 
public void notifyObservers() { 
notifyObservers(null); 
} 
// 通知所有observer(有參) 
@SuppressWarnings("unchecked") 
public void notifyObservers(Object data) { 
int size = 0; 
Observer[] arrays = null; 
synchronized (this) { 
if (hasChanged()) { 
clearChanged(); 
size = observers.size(); 
arrays = new Observer[size]; 
observers.toArray(arrays); 
} 
} 
if (arrays != null) { 
for (Observer observer : arrays) { 
observer.update(this, data); 
} 
} 
} 

注意:在Observer對象銷毀前一定要用deleteObserver將其從列表中刪除,也就是在onDestroy()方法中調(diào)用deleteObserver()方法。

不然因為還存在對象引用的關(guān)系,Observer對象不會被垃圾收集,造成內(nèi)存泄漏,并且已死的Observer仍會被通知到,有可能造成意料外的錯誤,而且隨著列表越來越大,notifyObservers操作也會越來越慢。

 觀察者模式所涉及的角色有:

  ●  抽象主題(Subject)角色:抽象主題角色把所有對觀察者對象的引用保存在一個聚集(比如ArrayList對象)里,每個主題都可以有任何數(shù)量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象,抽象主題角色又叫做抽象被觀察者(Observable)角色。

  ●  具體主題(ConcreteSubject)角色:將有關(guān)狀態(tài)存入具體觀察者對象;在具體主題的內(nèi)部狀態(tài)改變時,給所有登記過的觀察者發(fā)出通知。具體主題角色又叫做具體被觀察者(Concrete Observable)角色。

  ●  抽象觀察者(Observer)角色:為所有的具體觀察者定義一個接口,在得到主題的通知時更新自己,這個接口叫做更新接口。

  ●  具體觀察者(ConcreteObserver)角色:存儲與主題的狀態(tài)自恰的狀態(tài)。具體觀察者角色實現(xiàn)抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題的狀態(tài) 像協(xié)調(diào)。如果需要,具體觀察者角色可以保持一個指向具體主題對象的引用。

相關(guān)文章

  • Spring Boot基礎(chǔ)學(xué)習(xí)之Mybatis操作中使用Redis做緩存詳解

    Spring Boot基礎(chǔ)學(xué)習(xí)之Mybatis操作中使用Redis做緩存詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot基礎(chǔ)學(xué)習(xí)之Mybatis操作中使用Redis做緩存的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧
    2018-11-11
  • 在IDEA中實現(xiàn)生成Maven依賴關(guān)系圖

    在IDEA中實現(xiàn)生成Maven依賴關(guān)系圖

    這篇文章主要介紹了在IDEA中實現(xiàn)生成Maven依賴關(guān)系圖方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 深入淺出探索Java分布式鎖原理

    深入淺出探索Java分布式鎖原理

    單體系統(tǒng)中,在高并發(fā)場景下想要訪問共享資源的時候,我們需要通過加鎖的方式來保證共享資源并發(fā)的安全性,確保在同一時刻只有一個線程對共享資源進(jìn)行操作
    2022-02-02
  • Java實現(xiàn)Elasticsearch查詢當(dāng)前索引全部數(shù)據(jù)的完整代碼

    Java實現(xiàn)Elasticsearch查詢當(dāng)前索引全部數(shù)據(jù)的完整代碼

    這篇文章主要介紹了如何在Java中實現(xiàn)查詢Elasticsearch索引中指定條件下的全部數(shù)據(jù),通過設(shè)置滾動查詢參數(shù)(scroll),可以一次性獲取滿足條件的數(shù)據(jù),而不需要限制每頁的查詢條數(shù)大小,這樣可以避免因數(shù)據(jù)量過大而引發(fā)的性能問題,需要的朋友可以參考下
    2025-02-02
  • Java中枚舉的實現(xiàn)原理介紹

    Java中枚舉的實現(xiàn)原理介紹

    大家好,本篇文章主要講的是Java中枚舉的實現(xiàn)原理介紹,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • Java創(chuàng)建可執(zhí)行的Jar文件的方法實踐

    Java創(chuàng)建可執(zhí)行的Jar文件的方法實踐

    創(chuàng)建的可執(zhí)行Jar文件實際就是在原始Jar的清單文件中添加了Main-Class的配置,本文主要介紹了Java創(chuàng)建可執(zhí)行的Jar文件的方法實踐,感興趣的可以了解一下
    2023-12-12
  • Java序列化常見的三個問題

    Java序列化常見的三個問題

    這篇文章主要介紹了Java序列化常見的三個問題,幫助大家更好的理解和學(xué)習(xí)JAVA,感興趣的朋友可以了解下
    2020-08-08
  • SpringBoot集成Spring Security用JWT令牌實現(xiàn)登錄和鑒權(quán)的方法

    SpringBoot集成Spring Security用JWT令牌實現(xiàn)登錄和鑒權(quán)的方法

    這篇文章主要介紹了SpringBoot集成Spring Security用JWT令牌實現(xiàn)登錄和鑒權(quán)的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Java CompletableFuture如何實現(xiàn)超時功能

    Java CompletableFuture如何實現(xiàn)超時功能

    這篇文章主要為大家介紹了實現(xiàn)超時功能的基本思路以及CompletableFuture(之后簡稱CF)是如何通過代碼實現(xiàn)超時功能的,需要的小伙伴可以了解下
    2025-01-01
  • springboot配置文件屬性變量引用方式${}和@@用法及區(qū)別說明

    springboot配置文件屬性變量引用方式${}和@@用法及區(qū)別說明

    這篇文章主要介紹了springboot配置文件屬性變量引用方式${}和@@用法及區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論

明水县| 武隆县| 阳西县| 宣城市| 建水县| 团风县| 西城区| 金山区| 延安市| 大新县| 无极县| 定南县| 德钦县| 锦州市| 武胜县| 正镶白旗| 华池县| 互助| 鄂托克前旗| 陆良县| 定兴县| 东兰县| 九龙城区| 鹰潭市| 台前县| 上栗县| 西平县| 高州市| 齐河县| 济源市| 吉林市| 岢岚县| 城固县| 建宁县| 公主岭市| 湖州市| 林芝县| 砚山县| 永定县| 额敏县| 沾化县|