自從jack的鴨子游戲得到成功之后,jack的好朋友夏流就覺得心里癢癢的,也想做出一番作為來。
所以,今天的主人公就是這位夏流童鞋。夏流是錢塘江觀測站的一名觀測員,需要向人民群眾反饋錢塘江的水位,水溫,風力,及水里的魚量等信息。在這里經常會有許多市民從他這里打聽當日的錢塘江的這些信息,以便于他們了解,好決定是不是要去江邊做點什么。
于是夏流決定做一個系統(tǒng),能夠自動反饋錢塘江的信息給熱心市民。每當錢塘江的相關信息有變化時,會自動發(fā)送到熱心市民手機上,通知他們。
在觀察者模式中,夏流做的這個錢塘江觀測系統(tǒng)便是一個主題(Subject),熱心市民便是一個觀察者(Observer)
我們定義兩個接口Subject和Observer ,因為我們是有格局,有情懷的程序猿,所以一般我們都是要面向接口編程。
在Subject中,我們定義三個方法,添加觀察者,刪除觀察者,通知觀察者。
在Observer中,只要更新主題發(fā)過來的消息就好,所以只有一個更新方法。
然后我們實現具體主題,也就是錢塘江觀測站,在錢塘江觀測站中,水位,水溫,風力,魚的條數都是它的屬性,還有一個是觀察者列表,所有的觀察者都存在這個ObserverList里。當有新的信息更新時,他就調用notifyObserver方法通知他們的觀察者去更新信息。
接著呢是實現觀察者了,這個市民就是具體的觀察者了。觀察者中維護了一個主題,這個主題就是他關注的那個主題,也就是錢塘江觀測站了,它有了這個主題就能夠把自己給添加到這個主題的觀察者列表中了。

夏流按照這個思路設計完了該系統(tǒng),卻遭到了一些熱心市民的抱怨。一位愛釣魚的王大伯說,我只要當天的水位和魚的數量信息,其他信息這么多給我并沒有軟用。
另一位愛游泳的劉叔叔說,我只要水溫很風力信息就夠了,這樣我才能知道我該不該下水游泳(當然在錢塘江游泳釣魚啥的都是非常危險的,這里只是舉個例子)
另一位愛拍照的王阿姨說,我只要風力信息,希望我能借助風力吹起我美麗的秀發(fā),用我的美顏相機定格住那美麗的瞬間
夏流聽到了各位熱心市民的意見,決定改善一下系統(tǒng)。
他想這樣的話,就在通知觀察者的時候,讓update方法不帶參數。反正他們內部已經維護了一個主題,讓他們自己根據自己所需去從這個主題中拿數據就好了。
以下是修改后的類圖

主要還是修改觀察者中的update方法,一個是直接通過update方法一股腦把所有信息傳過來,另一個是通過觀察者自身所維護的主題中去取。
接著有了這個設計,我們好實現代碼了
package qiantang;
/**
* Created by huangx on 2018/11/14.
*/
public interface Observer {
void update();
? ? void display();
}
package qiantang;
/**
* Created by huangx on 2018/11/14.
*/
public interface Subject {
void addObserver(Observer observer);
? ? void deleteObserver(Observer observer);
? ? void notifyObserver();
}
package qiantang;
import java.util.ArrayList;
import java.util.List;
/**
* Created by huangx on 2018/11/14.
*/
public class QiangtangRiverStationimplements Subject {
private int height;
? ? private int tempature;
? ? private int wind;
? ? private int fish;
? ? private ListobserverList =new ArrayList();
? ? public void addObserver(Observer observer) {
observerList.add(observer);
? ? }
public void deleteObserver(Observer observer) {
observerList.remove(observer);
? ? }
public void notifyObserver() {
for (Observer observer :observerList) {
observer.update();
? ? ? ? }
}
public void setNewInfo(int height, int tempature, int wind, int fish) {
this.height = height;
? ? ? ? this.tempature = tempature;
? ? ? ? this.wind = wind;
? ? ? ? this.fish = fish;
? ? ? ? notifyObserver();
? ? }
public int getHeight() {
return height;
? ? }
public int getTempature() {
return tempature;
? ? }
public int getWind() {
return wind;
? ? }
public int getFish() {
return fish;
? ? }
}
package qiantang;
/**
* Created by huangx on 2018/11/14.
*/
public class FishCitizenimplements Observer {
private Stringname;
? ? private int fish;
? ? private int height;
? ? private Subjectsubject;
? ? public FishCitizen(String name, Subject subject) {
this.name = name;
? ? ? ? this.subject = subject;
? ? ? ? subject.addObserver(this);//關鍵一步把自己扔到主題中去
? ? }
public void update() {
if (subject instanceof QiangtangRiverStation) {
this.fish = ((QiangtangRiverStation)subject).getFish();
? ? ? ? ? ? this.height = ((QiangtangRiverStation)subject).getHeight();
? ? ? ? }
display();
? ? }
public void display() {
System.out.println("我是" +name +",今天的魚量是" +fish +",今天 的水位是" +height);
? ? }
}
package qiantang;
/**
* Created by huangx on 2018/11/14.
*/
public class SwimCitizenimplements Observer {
private Stringname;
? ? private int tempature;
? ? private int wind;
? ? private Subjectsubject;
? ? public SwimCitizen(String name, Subject subject) {
this.name = name;
? ? ? ? this.subject = subject;
? ? ? ? subject.addObserver(this);
? ? }
public void update() {
if (subject instanceof QiangtangRiverStation) {
this.tempature = ((QiangtangRiverStation)subject).getTempature();
? ? ? ? ? ? this.wind = ((QiangtangRiverStation)subject).getWind();
? ? ? ? }
display();
? ? }
public void display() {
System.out.println("我是" +name +",今天的溫度是" +tempature +",今天 的風力是" +wind);
? ? }
}
package qiantang;
/**
* Created by huangx on 2018/11/14.
*/
public class PhotoCitizenimplements Observer {
private Stringname;
? ? private int wind;
? ? private Subjectsubject;
? ? public PhotoCitizen(String name, Subject subject) {
this.name = name;
? ? ? ? this.subject = subject;
? ? ? ? subject.addObserver(this);
? ? }
public void update() {
if (subject instanceof QiangtangRiverStation) {
this.wind = ((QiangtangRiverStation)subject).getWind();
? ? ? ? }
display();
? ? }
public void display() {
System.out.println("我是" +name +",今天的風力是" +wind +"今天的我一定是個小公舉");
? ? }
}
package qiantang;
/**
* Created by huangx on 2018/11/14.
*/
public class TestApplication {
public static void main(String[] args) {
QiangtangRiverStation qiangtangRiverStation=new QiangtangRiverStation();
? ? ? ? SwimCitizen swimCitizen=new SwimCitizen("劉叔叔",qiangtangRiverStation);
? ? ? ? FishCitizen fishCitizen=new FishCitizen("王大伯",qiangtangRiverStation);
? ? ? ? PhotoCitizen photoCitizen=new PhotoCitizen("王阿姨",qiangtangRiverStation);
? ? ? ? qiangtangRiverStation.setNewInfo(11,22,33,44);
? ? ? ? qiangtangRiverStation.setNewInfo(55,66,77,88);
? ? }
}
運行結果:

有了這個設計,夏流童鞋不僅受到了大伯大媽的好評,也幫助他成為杭州杰出青年的好榜樣。
觀察者模式的官方定義是:定義對象見的一種一對多的依賴關系,當一個對象的狀態(tài)發(fā)送變化時,所有依賴它的對象都得到通知并被自動更新。