觀察者模式(Observer Pattern)
觀察者模式(Observer Pattern)也叫發佈訂閱模式(Publish/subscribe),它是一個在項目中經常 的模式,其定義如下:
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. (定義對象間一種“一對多”的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新)
觀察者的通用類圖
- Subject 被觀察者
定義被觀察者必須實現的職責,它必須能夠動態地增加、取消觀察者。它一般是抽象類或者是實現類,僅僅完成作爲被觀察者必須實現的職責:管理觀察者並通知觀察者。 - Observer觀察者
觀察者接收到消息後,即進行update(更新方法)操作,對接收到的信息進行處理。 - ConcreteSubject具體的被觀察者
定義被觀察者自己的業務,同時定義對哪些事件行通知。 - ConcreteObserver具體的觀察者
每個觀察者在接收到消息後的處理反應是不同的,各個觀察者有自己的處理邏輯。
觀察者模式的優點
1. 觀察者和被觀察者之間是抽象耦合
如何設計,則不 管是增加觀察者還是被觀察者都非常容易,而且在Java中都已經被蓋同的層級的定義,在系統方面更是得心應手。
2. 建立一套觸發機制
根據單一職責原則,每個類的職責是單一的,那麼怎麼把這個單一的串聯成真實世界的複雜邏輯關係呢?比如我們去打獵,打死了一隻母鹿,母鹿有三個幼崽,因後援會以了母鹿而餓死,繼而……然後……這就是一個觸發機制,形成了一個觸發鏈。觀察者模式可以完美實現這裏的鏈條形式。
觀察者模式的缺點
觀察者模式需要考慮一下開發效率和運行效率量,一個空間站以者,多個觀察者,開發和高度就會比較複雜,而且Java中消息的通知默認是順序執行,一個觀察者卡殼,會影響整體的執行效率。在這種情況下,一般考慮採用異步的方式。
多級觸發時的效率更是讓人擔憂,大家在設計時注意考慮。
觀察者模式的使用場景
1. 關聯行爲場景。需要注意的是,關聯行爲是可拆分的,而不是“組合”關係。
2. 事件多級觸發場景。
3. 跨系統的消息交換場景,如消息隊列的處理機制。
Subject類
package patterns.Observer.useUtil;
import java.util.Observable;
public class 信息暴露狂 extends Observable {
private int 道德 = 50;
private int 智商 = 50;
private int 體重 = 50;
public 信息暴露狂() {
System.out.println("我是暴露狂,我做什麼事都要讓別人知道!!!");
}
@Override
public String toString() {
return "目前此人 道德"+道德+" 智商"+智商+" 體重"+體重;
}
public void 吃() {
System.out.println("我吃");
體重++;
setChanged(); //此處不調不觸發下一句事件!!!!特別注意!!!
this.notifyObservers("各種美拍高大上");
}
public void 喝() {
System.out.println("我喝");
體重++;
setChanged();
this.notifyObservers("各種美拍高大上");
}
public void 拉() {
System.out.println("我拉");
體重--;
setChanged();
this.notifyObservers("各種美拍高大上");
}
public void 撒() {
System.out.println("我撒");
體重--;
setChanged();
this.notifyObservers("各種美拍高大上");
}
public void 睡() {
System.out.println("我睡");
setChanged();
this.notifyObservers("各種美拍高大上");
}
public void 坑() {
System.out.println("我坑");
道德--;
setChanged();
this.notifyObservers("各種美拍高大上");
}
public void 蒙() {
System.out.println("我蒙");
智商--;
setChanged();
this.notifyObservers("各種美拍高大上");
}
public void 拐() {
System.out.println("我拐");
體重--;
道德--;
setChanged();
this.notifyObservers("各種美拍高大上");
}
public void 騙() {
System.out.println("我騙");
智商++;
道德--;
setChanged();
this.notifyObservers("各種美拍高大上");
}
public void 偷() {
System.out.println("我偷");
體重--;
道德--;
setChanged();
this.notifyObservers("各種美拍高大上");
}
public void 學習() {
System.out.println("我學習");
智商++;
道德++;
setChanged();
this.notifyObservers("各種美拍高大上");
}
public int get道德() {
return 道德;
}
public int get智商() {
return 智商;
}
public int get體重() {
return 體重;
}
}
Main
package patterns.Observer.useUtil;
import java.util.Observable;
import java.util.Observer;
public class Client {
//觀察者模式執行場景
public static void main(String[] args) {
Observer 朋友圈 = new Observer() {
@Override
public void update(Observable o, Object arg) {
//處理傳來的值
if(o instanceof 信息暴露狂){
信息暴露狂 human = (信息暴露狂)o;
//“拉”信息
int 道德 = 10*human.get道德();
int 智商 = 10*human.get智商();
int 體重 = 10*human.get體重();
String after = arg+"加道德"+道德+"、加智商"+智商+"、加體重"+體重+"=====";
System.out.println("發到【朋友圈】:"+after+" - "+o);
}
}
};
Observer 微博 = new Observer() {
@Override
public void update(Observable o, Object arg) {
//“推”信息
System.out.println("發到【微博】:"+arg+" - "+o);
}
};
信息暴露狂 老陳頭 = new 信息暴露狂();
老陳頭.addObserver(朋友圈);
老陳頭.吃();
老陳頭.喝();
老陳頭.addObserver(微博); //拉巴巴的時候註冊了微博
老陳頭.拉();
老陳頭.撒();
老陳頭.睡();
老陳頭.坑();
老陳頭.deleteObserver(朋友圈); //不再玩朋友圈了
老陳頭.蒙();
老陳頭.拐();
老陳頭.騙();
老陳頭.偷();
老陳頭.學習();
}
}
運行結果
我是暴露狂,我做什麼事都要讓別人知道!!!
我吃
發到【朋友圈】:各種美拍高大上加道德500、加智商500、加體重510===== - 目前此人 道德50 智商50 體重51
我喝
發到【朋友圈】:各種美拍高大上加道德500、加智商500、加體重520===== - 目前此人 道德50 智商50 體重52
我拉
發到【微博】:各種美拍高大上 - 目前此人 道德50 智商50 體重51
發到【朋友圈】:各種美拍高大上加道德500、加智商500、加體重510===== - 目前此人 道德50 智商50 體重51
我撒
發到【微博】:各種美拍高大上 - 目前此人 道德50 智商50 體重50
發到【朋友圈】:各種美拍高大上加道德500、加智商500、加體重500===== - 目前此人 道德50 智商50 體重50
我睡
發到【微博】:各種美拍高大上 - 目前此人 道德50 智商50 體重50
發到【朋友圈】:各種美拍高大上加道德500、加智商500、加體重500===== - 目前此人 道德50 智商50 體重50
我坑
發到【微博】:各種美拍高大上 - 目前此人 道德49 智商50 體重50
發到【朋友圈】:各種美拍高大上加道德490、加智商500、加體重500===== - 目前此人 道德49 智商50 體重50
我蒙
發到【微博】:各種美拍高大上 - 目前此人 道德49 智商49 體重50
我拐
發到【微博】:各種美拍高大上 - 目前此人 道德48 智商49 體重49
我騙
發到【微博】:各種美拍高大上 - 目前此人 道德47 智商50 體重49
我偷
發到【微博】:各種美拍高大上 - 目前此人 道德46 智商50 體重48
我學習
發到【微博】:各種美拍高大上 - 目前此人 道德47 智商51 體重48