日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

观察者模式重复调用mysql问题,2、观察者模式

發(fā)布時(shí)間:2025/3/21 数据库 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 观察者模式重复调用mysql问题,2、观察者模式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

整理: 氣象站的故事 現(xiàn)在我們要為一家氣象站開(kāi)發(fā)一套氣象監(jiān)控系統(tǒng),按照客戶的要求,這個(gè)監(jiān)控系統(tǒng)必須可以實(shí)時(shí)跟蹤當(dāng)前的天氣狀況(溫度、濕度、大氣壓力),并且可以在三種不同設(shè)備上顯示出來(lái)(當(dāng)前天氣狀況、天氣統(tǒng)計(jì)、天氣預(yù)測(cè))。客戶還希望這個(gè)系統(tǒng)可以對(duì)外

整理:

氣象站的故事

現(xiàn)在我們要為一家氣象站開(kāi)發(fā)一套氣象監(jiān)控系統(tǒng),按照客戶的要求,這個(gè)監(jiān)控系統(tǒng)必須可以實(shí)時(shí)跟蹤當(dāng)前的天氣狀況(溫度、濕度、大氣壓力),并且可以在三種不同設(shè)備上顯示出來(lái)(當(dāng)前天氣狀況、天氣統(tǒng)計(jì)、天氣預(yù)測(cè))。客戶還希望這個(gè)系統(tǒng)可以對(duì)外提供一個(gè)API接口,以便任何開(kāi)發(fā)者都可以開(kāi)發(fā)自己的顯示設(shè)備,然后無(wú)縫掛接到系統(tǒng)中,系統(tǒng)可以統(tǒng)一更新所有顯示設(shè)備的數(shù)據(jù)。客戶還會(huì)提供一個(gè)可以訪問(wèn)氣象站的硬件設(shè)備的組件,如下圖所示:

它提供了三個(gè)方法(get開(kāi)頭),可以分別取得實(shí)時(shí)的溫度、濕度和大氣壓力,還有一個(gè)MeasurementsChanged()方法,當(dāng)任何天氣狀況發(fā)生變化的時(shí)候,這個(gè)方法都會(huì)自動(dòng)被觸發(fā),當(dāng)前這個(gè)方法只是一個(gè)空函數(shù),擴(kuò)展的代碼還需要我們自己去擴(kuò)充。至于WeatherData是如何取得天氣狀況的,還有MeasurementsChanged()方法是如何被自動(dòng)觸發(fā)的這些事情都不需要我們?nèi)タ紤],我們只管考慮如果做好跟顯示設(shè)備有關(guān)的事情就好了。

OK!讓我們來(lái)考慮一下這個(gè)系統(tǒng)的實(shí)現(xiàn),先重新理一下思路:

1. 客戶提供了獲取實(shí)時(shí)的天氣狀況的方法。

2. MeasurementsChanged()方法會(huì)在天氣狀況變化時(shí)被自動(dòng)調(diào)用。

3. 系統(tǒng)要實(shí)現(xiàn)三種顯示模式,分別顯示天氣狀況、天氣統(tǒng)計(jì)和天氣預(yù)測(cè),而且這些顯示的信息必須跟當(dāng)前最新的天氣狀況實(shí)時(shí)同步。

4. 系統(tǒng)還必須支持在顯示方式上的擴(kuò)展性,而且使用者可以任意添加和移除不同的顯示模式。

基于上面這些信息,我們大概都會(huì)想到可以象下面這樣來(lái)實(shí)現(xiàn)這個(gè)系統(tǒng):

//偽代碼

public class WeatherData

{

//實(shí)例化顯示設(shè)備(省略)

public void MeasurementsChanged()

{

float temp = getTemperature(); //取得溫度

float humidity = getHumidity(); //取得濕度

float pressure = getPressure(); //取得氣壓

currentConditionsDisplay.update(temp, humidity, pressure); //同步顯示當(dāng)前天氣狀況

statisticsDisplay.update(temp, humidity, pressure); //同步顯示天氣統(tǒng)計(jì)信息

forecastDisplay.update(temp, humidity, pressure); //同步顯示天氣預(yù)報(bào)信息

}

}

因?yàn)榭蛻粢呀?jīng)給我們提供了實(shí)時(shí)的數(shù)據(jù),還提供了數(shù)據(jù)更新時(shí)候的觸發(fā)機(jī)制,那么我們要做的就是把最新的數(shù)據(jù)提供給不同的顯示設(shè)備就OK了,上面的代碼好象已經(jīng)可以基本解決問(wèn)題啦。哈哈!

面向接口編程,而不要面向?qū)崿F(xiàn)編程。”的原則,這樣實(shí)現(xiàn)會(huì)帶來(lái)的問(wèn)題是系統(tǒng)無(wú)法滿足在不修改代碼的情況下動(dòng)態(tài)添加或移除不同的顯示設(shè)備。換句話說(shuō),顯示設(shè)備相關(guān)的部分是系統(tǒng)中最不穩(wěn)定的部分,應(yīng)該將其單獨(dú)隔離開(kāi),也就是前面學(xué)過(guò)的另一個(gè)原則:“找到系統(tǒng)中變化的部分,將變化的部分同其它穩(wěn)定的部分隔開(kāi)。”那么我們到底該怎么辦呢?呵呵,既然這篇文章是講觀察者模式的,當(dāng)然要用它來(lái)結(jié)束戰(zhàn)斗!下面我們先來(lái)認(rèn)識(shí)一下觀察者模式~

這就是觀察者模式

我們還是先看一下官方的定義:

The Observer Patterndefines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically. (觀察者模式定義了對(duì)象間的一種一對(duì)多依賴(lài)關(guān)系,使得每當(dāng)一個(gè)對(duì)象改變狀態(tài),則所有依賴(lài)于它的對(duì)象都會(huì)得到通知并被自動(dòng)更新)

咋樣?這是超級(jí)經(jīng)典的標(biāo)準(zhǔn)定義,如假抱換的!不懂?那再看看下面的類(lèi)圖吧~

Subject(被觀察的對(duì)象接口)

l 規(guī)定ConcreteSubject的統(tǒng)一接口;

l 每個(gè)Subject可以有多個(gè)Observer;

ConcreteSubject(具體被觀察對(duì)象)

l 維護(hù)對(duì)所有具體觀察者的引用的列表;

l 狀態(tài)發(fā)生變化時(shí)會(huì)發(fā)送通知給所有注冊(cè)的觀察者。

Observer(觀察者接口)

l 規(guī)定ConcreteObserver的統(tǒng)一接口;

l 定義了一個(gè)update()方法,在被觀察對(duì)象狀態(tài)改變時(shí)會(huì)被調(diào)用。

ConcreteObserver(具體觀察者)

l 維護(hù)一個(gè)對(duì)ConcreteSubject的引用;

l 特定狀態(tài)與ConcreteSubject同步;

l 實(shí)現(xiàn)Observer接口,通過(guò)update()方法接收ConcreteSubject的通知。

怎么樣,現(xiàn)在總該有點(diǎn)感覺(jué)了吧?下面還有一個(gè)順序圖,再體會(huì)體會(huì)~

呵呵!還沒(méi)想明白,為什么官方的東西總是看不懂,看來(lái)是沒(méi)當(dāng)官的命啦!其實(shí)觀察者模式十分簡(jiǎn)單,現(xiàn)實(shí)生活中的例子更是隨處可見(jiàn),就比如看電視:某個(gè)觀眾就是一個(gè)標(biāo)準(zhǔn)的ConcreteObserver(具體觀察者,都符合統(tǒng)一的Observer接口,即都要通過(guò)電視收看節(jié)目的觀眾),電視節(jié)目就是Subject(被觀察對(duì)象接口,這里體現(xiàn)為無(wú)線電視信號(hào))了,不同的頻道的節(jié)目是不同的ConcreteSubject(不同頻道有不同的節(jié)目),觀眾可以自由決定看電視(registerObserver)或不看電視(removeObserver),而電視節(jié)目的變化也會(huì)在自動(dòng)更新(notifyObservers)所有觀眾的收看內(nèi)容。怎么樣?這回明白了吧!

另外觀察者模式也叫發(fā)布-訂閱模式(Publishers + Subscribers = Observer Pattern),跟看電視一樣,訂閱報(bào)紙也是一個(gè)很直觀的例子,有人發(fā)布(Publish = Subject)報(bào)紙,有人訂閱(Subscribe = Observer)報(bào)紙,訂閱的人可以定期收到最新發(fā)布的報(bào)紙,訂閱人也可以隨時(shí)退訂。

現(xiàn)在大家應(yīng)該對(duì)觀察者模式基本都了解了,我們來(lái)用這個(gè)模式來(lái)解決氣象站哪個(gè)問(wèn)題。就氣象站問(wèn)題的應(yīng)用場(chǎng)景來(lái)說(shuō),WeatherData可以作為ConcreteSubject來(lái)看待,而不同的顯示設(shè)備則可以作為ConcreteObserver來(lái)看待,也就是說(shuō)顯示設(shè)備觀察WeatherData對(duì)象,如果WeatherData對(duì)象有任何狀態(tài)變化,則立刻更新顯示設(shè)備的數(shù)據(jù)信息。這么說(shuō)似乎很靠譜了,下面我們?cè)賮?lái)具體實(shí)現(xiàn)一下吧,先從整體結(jié)構(gòu)開(kāi)始,如下類(lèi)圖:

跟前面說(shuō)的實(shí)現(xiàn)方式完全一樣,只是這里為所有顯示設(shè)備又定義了一個(gè)統(tǒng)一的接口,這個(gè)接口里定義了一個(gè)display()方法,也就是說(shuō)未來(lái)所有實(shí)現(xiàn)Observer和DisplayElement接口的對(duì)象應(yīng)該都可以作為氣象監(jiān)控系統(tǒng)的終端顯示設(shè)備,不同用戶可以在display()方法里任意自定義自己的顯示模式。因?yàn)闉榱朔乐够靵y,圖4中只畫(huà)了一個(gè)具體顯示設(shè)備對(duì)象,即CurrentConditionsDisplay,跟它同級(jí)別的還有StatisticsDisplay和ForcastDisplay,它們?cè)诮Y(jié)構(gòu)上完全相同。下面我們通過(guò)具體的代碼再進(jìn)一步理解一下基于觀察者模式的氣象監(jiān)控系統(tǒng)的實(shí)現(xiàn)。

ISubject:

public interface Subject {

public void registerObserver(Observer observer);

public void removeObserver(Observer observer);

public void notifyObservers();

}

關(guān)于這段代碼,似乎沒(méi)什么好說(shuō)的了,因?yàn)樯厦嬉呀?jīng)反復(fù)說(shuō)了很多啦。

IObserver:

public interface Observer {

public void update(float temp, float humidity, float pressure);

}

這里我們給update()方法定義了三個(gè)對(duì)應(yīng)不同氣象數(shù)據(jù)的參數(shù)。

DisplayElement :

public interface DisplayElement {

public void display();

}

這個(gè)類(lèi)也是超級(jí)簡(jiǎn)單,沒(méi)什么可解釋的。

WeatherData:

public class WeatherData implements Subject {

private ArrayList observers;

private float temp;

private float humidity;

private float pressure;

public WeatherData() {

this.observers = new ArrayList();

}

@Override

public void notifyObservers() {

for (int i = 0; i < observers.size(); i++) {

Observer observer = (Observer) observers.get(i);

observer.update(temp, humidity, pressure);

}

}

@Override

public void registerObserver(Observer observer) {

observers.add(observer);

}

@Override

public void removeObserver(Observer observer) {

int i = observers.indexOf(observer);

if (i >= 0) {

observers.remove(i);

}

}

public void measurementsChanged() {

notifyObservers();

}

public void setMeasurements(float temp, float humidity, float pressure) {

this.temp = temp;

this.humidity = humidity;

this.pressure = pressure;

measurementsChanged();

}

}

這個(gè)類(lèi)是ISubject的具體實(shí)現(xiàn),內(nèi)部使用ArrayList來(lái)記錄所有注冊(cè)的觀察者,SetMeasurements() 方法是用來(lái)模擬前面提到的在天氣狀況改變的時(shí)候自動(dòng)觸發(fā)MeasurementsChanged()方法的機(jī)制。

CurrentConditionsDisplay:

public class CurrentConditionDisplay implements Observer, DisplayElement {

private Subject weatherData;

private float temp;

private float humidity;

public CurrentConditionDisplay(Subject weatherData) {

this.weatherData = weatherData;

weatherData.registerObserver(this);

}

@Override

public void update(float temp, float humidity, float pressure) {

this.temp = temp;

this.humidity = humidity;

display();

}

@Override

public void display() {

System.out.println("CurrentConditionDisplay temp = " + temp

+ " humidity = " + humidity);

}

}

這個(gè)類(lèi)是IObserver和IDisplayElement的具體實(shí)現(xiàn),代表顯示當(dāng)前天氣狀況的具體顯示設(shè)備對(duì)象,其內(nèi)部維護(hù)了一個(gè)ISubject類(lèi)型的變量,該變量在CurrentConditionsDisplay的構(gòu)造函數(shù)中被初始化,同時(shí)調(diào)用ISubject.registerObserver()方法,實(shí)現(xiàn)訂閱ISubject。

StatisticsDisplay和ForcastDisplay:

public class ForecastDisplay implements Observer, DisplayElement {

private Subject weatherData;

private float temp;

private float humidity;

private float pressure;

public ForecastDisplay(Subject weatherData) {

this.weatherData = weatherData;

weatherData.registerObserver(this);

}

@Override

public void update(float temp, float humidity, float pressure) {

this.temp = temp;

this.humidity = humidity;

this.pressure = pressure;

display();

}

@Override

public void display() {

System.out.println("ForecastDisplay temp = " + temp + " pressure = "

+ pressure);

}

}

StatisticsDisplay代碼類(lèi)似。

測(cè)試代碼:

public class WeatherTest {

public static void main(String[] args) {

WeatherData weatherData = new WeatherData();

CurrentConditionDisplay currentDisplay = new CurrentConditionDisplay(

weatherData);

ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);

weatherData.setMeasurements(80f, 90f, 30.4f);

weatherData.setMeasurements(100f, 99f, 40.0f);

}

}

..

使用JDK內(nèi)置的觀察者模式

若使用java內(nèi)置的觀察者模式,則 Subject 需要繼承 java.util.Observable 類(lèi)和, 觀察者實(shí)現(xiàn)java.util.Observer接口,具體代碼如下:

public class WeatherData extends Observable {

private float temp;

private float humidity;

private float pressure;

public WeatherData() {

//此時(shí)已經(jīng)不需要我們自己定義存放觀察者的數(shù)據(jù)結(jié)構(gòu)了。

}

public void measurementsChanged() {

setChanged();

notifyObservers();// 調(diào)用notifyObservers方法之前,需先調(diào)用setChanged方法,來(lái)指示狀態(tài)已經(jīng)改變

/**

* Observable 類(lèi)中notifyObservers代碼如下: 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); } }

*

* Observable 類(lèi)中方法:

* protected synchronized void setChanged() { changed = true; }

**/

}

public void setMeasurements(float temp, float humidity, float pressure) {

this.temp = temp;

this.humidity = humidity;

this.pressure = pressure;

measurementsChanged();

}

public float getTemp() {// 定義此方法,只因?yàn)橛^察者用它來(lái)“拉”數(shù)據(jù)

return temp;

}

public float getHumidity() {

return humidity;

}

public float getPressure() {

return pressure;

}

}

觀察者的定義如下:

public class CurrentConditionDisplay implements Observer, DisplayElement {

private Observable weatherData;

private float temp;

private float humidity;

public CurrentConditionDisplay(Observable weatherData) {

this.weatherData = weatherData;

weatherData.addObserver(this);

}

@Override

public void display() {

System.out.println("CurrentConditionDisplay temp = " + temp

+ " humidity = " + humidity);

}

@Override

public void update(Observable obs, Object arg) {

if (obs instanceof WeatherData) {

WeatherData weatherData = (WeatherData) obs;

this.temp = weatherData.getTemp();

this.humidity = weatherData.getHumidity();

display();

}

}

}

其余代碼與上面自己定義接口的類(lèi)似。

應(yīng)用場(chǎng)景和優(yōu)缺點(diǎn)

上面已經(jīng)對(duì)觀察者模式做了比較詳細(xì)的介紹,還是那句話,人無(wú)完人,模式也不是萬(wàn)能的,我們要用好設(shè)計(jì)模式來(lái)解決我們的實(shí)際問(wèn)題,就必須熟知模式的應(yīng)用場(chǎng)景和優(yōu)缺點(diǎn):

觀察者模式的應(yīng)用場(chǎng)景:

1、 對(duì)一個(gè)對(duì)象狀態(tài)的更新,需要其他對(duì)象同步更新,而且其他對(duì)象的數(shù)量動(dòng)態(tài)可變。

2、 對(duì)象僅需要將自己的更新通知給其他對(duì)象而不需要知道其他對(duì)象的細(xì)節(jié)。

觀察者模式的優(yōu)點(diǎn):

1、 Subject和Observer之間是松偶合的,分別可以各自獨(dú)立改變。

2、 Subject在發(fā)送廣播通知的時(shí)候,無(wú)須指定具體的Observer,Observer可以自己決定是否要訂閱Subject的通知。

3、 遵守大部分GRASP原則和常用設(shè)計(jì)原則,高內(nèi)聚、低偶合。

觀察者模式的缺陷:

1、 松偶合導(dǎo)致代碼關(guān)系不明顯,有時(shí)可能難以理解。(廢話)

2、 如果一個(gè)Subject被大量Observer訂閱的話,在廣播通知的時(shí)候可能會(huì)有效率問(wèn)題。(畢竟只是簡(jiǎn)單的遍歷)

參考:http://www.cnblogs.com/justinw/archive/2007/05/02/734522.html#!comments

本文原創(chuàng)發(fā)布php中文網(wǎng),轉(zhuǎn)載請(qǐng)注明出處,感謝您的尊重!

總結(jié)

以上是生活随笔為你收集整理的观察者模式重复调用mysql问题,2、观察者模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。