日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
淺析JDKObserver設(shè)計(jì)模式

Java中JDK自帶的JDK Observer設(shè)計(jì)模式的實(shí)現(xiàn)是一個(gè)范例,有助于我們?cè)谠O(shè)計(jì)模式的思維上有所突破。目前設(shè)計(jì)模式的介紹性文章越來(lái)越多,但設(shè)計(jì)模式的研究性文章仍然比較欠缺,這著實(shí)讓人覺(jué)得有點(diǎn)遺憾。本文旨在拋磚引玉。

成都創(chuàng)新互聯(lián)公司專(zhuān)注為客戶(hù)提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、泗水網(wǎng)絡(luò)推廣、小程序定制開(kāi)發(fā)、泗水網(wǎng)絡(luò)營(yíng)銷(xiāo)、泗水企業(yè)策劃、泗水品牌公關(guān)、搜索引擎seo、人物專(zhuān)訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供泗水建站搭建服務(wù),24小時(shí)服務(wù)熱線:18982081108,官方網(wǎng)址:www.cdcxhl.com

1.JDK Observer設(shè)計(jì)模式概要

JDK Observer設(shè)計(jì)模式在GOF里屬于行為設(shè)計(jì)模式。JDK里提供的observer設(shè)計(jì)模式的實(shí)現(xiàn)由java.util.Observable類(lèi)和java.util.Observer接口組成。從名字上可以清楚的看出兩者在Observer 設(shè)計(jì)模式中分別扮演的角色:Observer是觀察者角色,Observable是被觀察目標(biāo)(subject)角色。

Observable是一個(gè)封裝subject基本功能的類(lèi),比如注冊(cè)observer(attach功能),注銷(xiāo)observer(detatch功能)等。這些功能是任何一個(gè)扮演observerable角色的類(lèi)都需要實(shí)現(xiàn)的,從這一點(diǎn)上來(lái)講,JDK里將這些通用功能專(zhuān)門(mén)封裝在一個(gè)類(lèi)里,顯得合情合理。通常情況下,我們的類(lèi)只要從Observerable類(lèi)派生就可以稱(chēng)為observerable角色類(lèi),使用非常簡(jiǎn)單。

2.使用JDK Observer設(shè)計(jì)模式存在的困難

但我們不得不注意到,在項(xiàng)目實(shí)際開(kāi)發(fā)當(dāng)中,情況往往要復(fù)雜得多。java不支持多繼承特性在很多時(shí)候是阻礙我們使用JDK Observer設(shè)計(jì)模式的絆腳石。比如說(shuō),我們?cè)O(shè)計(jì)的一個(gè)類(lèi)已經(jīng)是某個(gè)類(lèi)的派生類(lèi),在這種情況下同時(shí)想讓它扮演Observerable角色將變得麻煩。如何實(shí)現(xiàn)“多繼承”的效果是擺在我們面前的一大難題。下面我們首先分析一下Observable類(lèi)。

3.JDK Observable類(lèi)“觸發(fā)通知”的原理

Observable必須“有變化”才能觸發(fā)通知observer這一任務(wù),這是它的本質(zhì)體現(xiàn)。查看源碼便可知一二。

Observerable部分源碼如下:

 
 
 
  1.   //……省略……
  2.   private boolean changed = false;
  3.   //……省略……
  4.   public void notifyObservers(Object arg) {
  5.   //……省略……
  6.     Object[] arrLocal;
  7.     synchronized (this) {
  8.      //……省略……
  9.      if (!changed)
  10.       return;
  11.       arrLocal = obs.toArray();
  12.       clearChanged();
  13.     }
  14.   //……省略……
  15.   protected synchronized void setChanged() {
  16.    changed = true;
  17.   }
  18.  
  19.   protected synchronized void clearChanged() {
  20.    changed = false;
  21.   }

正如粗的斜體標(biāo)注部分所示,在notifyObservers(Object arg) 方法里if (!changed) return;語(yǔ)句告訴我們,若changed屬性值為false,將直接返回,根本不會(huì)觸發(fā)通知操作。并且我們注意到changed 屬性被初始化為false,這將意味著如果我們不主動(dòng)設(shè)置changed屬性為true,將不會(huì)有任何變化,也就是說(shuō)根本起不到“通知”作用。因此,設(shè)置changed屬性的值是我們應(yīng)用jdk observer 設(shè)計(jì)模式的關(guān)鍵所在。那么如何才能設(shè)置changed屬性呢?從源碼可以看出,唯一的入口是通過(guò)setChanged()。下面我們分析一下changed屬性及相關(guān)的方法setChanged()和clearChanged()。

4.Observable類(lèi)的分析

Observable#changed屬性的初始值為false,這很容易理解,不再詳細(xì)陳述。細(xì)心的讀者可能會(huì)注意到跟changed屬性有關(guān)的兩個(gè)方法setChanged()和clearChanged(),它們的修飾符都是protected。想強(qiáng)調(diào)的是,是protected,而不是public。但這樣是否有其必要性和合理性?答案是肯定的。在前面的分析中,我已經(jīng)提到,setChanged()方法是設(shè)置changed的唯一入口,它的修飾符定義為protected,就意味著通過(guò)定義Observable的對(duì)象,再設(shè)置changed屬性將變得不可能。從這個(gè)意義上說(shuō),要想應(yīng)用observer設(shè)計(jì)模式,必須繼承Observable類(lèi)方可。關(guān)于這一點(diǎn),下文還會(huì)提及。但是,為什么不能定義成public?這似乎難以理解。因?yàn)槎x成public,我們不就可以很方便地設(shè)置changed屬性的值嗎?為了弄清楚這個(gè)問(wèn)題,我們還是看一下Observable里的相關(guān)的代碼:

 
 
 
  1.   //……省略……
  2.   public void notifyObservers(Object arg) {
  3.   //……省略……
  4.    for (int i = arrLocal.length-1; i>=0; i--)
  5.     ((Observer)arrLocal[i]).update(this, arg);
  6.   }

    
這段代碼表達(dá)的意思是說(shuō)找出所有已注冊(cè)的Observer,再逐個(gè)進(jìn)行“通知”,通過(guò)調(diào)用Observer#update(Observable,Object)方法進(jìn)行通知。我們看到,update 第一個(gè)參數(shù)是this,我們同時(shí)還必須注意到,這段代碼是Observable類(lèi)里的代碼。這就相當(dāng)于是在一再?gòu)?qiáng)調(diào),發(fā)出“通知”的,必須是observable自己(Observable類(lèi)或者其派生類(lèi)),其它任何類(lèi)都不行。這就意味著我們的observable類(lèi)繼承Observable類(lèi)是必要的,因?yàn)槿绻焕^承,而采用組合的話(huà),將無(wú)法保證能傳遞好this。換句話(huà)說(shuō),采用組合的方式使用Observable類(lèi),將變得幾乎沒(méi)有任何意義。同時(shí),修飾符定義為protected,可以確保是在Obsrvable里進(jìn)行觸發(fā)通知的,不會(huì)在其它任何地方進(jìn)行通知,這顯得內(nèi)斂性很強(qiáng)。如果將setChanged()修飾符定義為public,將無(wú)法保證正確“傳遞this”的硬性要求,這不符合“只有observalbe才能直接或間接通知observer”這一observable設(shè)計(jì)模式的硬性要求。由此我們可見(jiàn)一斑,jdk的很多理念的思想性是多么的強(qiáng)。

5.解決使用observer設(shè)計(jì)模式存在的困難

借助adapter設(shè)計(jì)模式(詳見(jiàn)本人發(fā)表的adapter設(shè)計(jì)模式相關(guān)文章)和java支持多接口特性基本可以解決“多繼承”問(wèn)題?;舅枷胧墙Y(jié)合繼承/實(shí)現(xiàn)和組合來(lái)達(dá)到效果。在上面的分析中,我們已經(jīng)知道,Observable類(lèi)必須繼承使用,不能組合使用,因此我們只需要將需扮演成observerable角色的類(lèi)裝扮成adapter角色,將該類(lèi)原繼承的類(lèi)裝扮成adaptee角色即可。示例代碼如下:

 
 
 
  1.   //欲充當(dāng)observable角色的類(lèi)的原來(lái)的代碼:
  2.   public class MyObject extends BaseObject {
  3.    public MyObject() {
  4.     public void method1(){}
  5.    }
  6.   }
  7.   //充當(dāng)observable角色后的代碼:
  8.   public class MyObject extends Observable {
  9.    private BaseObject baseObject = null;
  10.     public MyObject(BaseObject baseObject) {
  11.      this.baseObject = baseObject;
  12.     }
  13.   }

6.JDK Observer注意事項(xiàng):

如果上例中的BaseObject也用到需要傳遞“this”的方法,那么上面的組合使用方法將有可能失效。這種情況是最糟糕的情況。此時(shí)可以考慮在BaseObject類(lèi)這些“瓶頸”地方盡量采用接口代替類(lèi)(包括抽象類(lèi))來(lái)解決。

那么JDK Observer設(shè)計(jì)模式就介紹到這里,但是很多的設(shè)計(jì)模式的思路還是要舉一反三慢慢提高。


當(dāng)前文章:淺析JDKObserver設(shè)計(jì)模式
URL標(biāo)題:http://www.5511xx.com/article/dhepgjg.html