??觀察者模式定義對(duì)象一對(duì)多的關(guān)系结洼,他希望一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),其他依賴于它的對(duì)象能夠接到通知并執(zhí)行相應(yīng)的處理邏輯叉跛。例如微信訂閱某個(gè)公眾號(hào)松忍,當(dāng)公眾號(hào)發(fā)布新文章時(shí),所有訂閱該公眾號(hào)的人都會(huì)收到文章推送消息筷厘。spring的事件機(jī)制是采用觀察者模式鸣峭,進(jìn)行業(yè)務(wù)的解耦的。
?? 觀察模式簡(jiǎn)單分為被觀察者和觀察者酥艳,實(shí)現(xiàn)原理為被觀察者有一個(gè)存放觀察者的集合摊溶,當(dāng)被觀察者發(fā)生狀態(tài)改變時(shí),通知所有的觀察者充石,觀察者處理相應(yīng)的邏輯莫换。
被觀察者
?? 這里簡(jiǎn)單用一個(gè)類(lèi)來(lái)描述被觀察者,它可以接收觀察者類(lèi)型,和更新?tīng)顟B(tài)拉岁,當(dāng)狀態(tài)更新時(shí)坷剧,會(huì)通知所有觀察者的onMessage()方法,處理相應(yīng)的邏輯喊暖。
import java.util.ArrayList;
import java.util.List;
@Data
public class Subject {
private List<Observer> observers = new ArrayList<Observer>();
public void update(){
notifyObervers();
}
public void addObserver(Observer observer) {
observers.add(observer);
}
private void notifyObervers(){
for (Observer observer: observers) {
observer.onMessage();
}
}
}
觀察者
這里定義觀察者惫企,它有一個(gè)指定具體名稱的構(gòu)造方法,和一個(gè)onMessage()方法哄啄,在被觀察者狀態(tài)發(fā)生改變時(shí)被調(diào)用
import lombok.Data;
@Data
public class Observer{
private String name;
public Observer(String name) {
this.name = name;
}
public void onMessage() {
System.out.println(name + "監(jiān)聽(tīng)到發(fā)布事件");
}
}
客戶端
當(dāng)我們定義好了被觀察者和觀察者雅任,使用一個(gè)類(lèi)來(lái)模擬相應(yīng)的測(cè)試流程风范。
這里定義了一個(gè)被觀察者和兩個(gè)觀察者咨跌,然后被觀察者更新?tīng)顟B(tài),那么其他的觀察者就會(huì)接到通知硼婿,然后處理事件锌半。
public class App {
public static void main(String[] args) {
Subject subject = new Subject();
Observer firstObserver = new Observer("firstObserver");
Observer secondObserver = new Observer("secondObserver");
subject.addObserver(firstObserver);
subject.addObserver(secondObserver);
subject.update();
}
}
輸出
firstObserver監(jiān)聽(tīng)到發(fā)布事件
secondObserver監(jiān)聽(tīng)到發(fā)布事件
升級(jí)版本
考慮到被觀察者進(jìn)行狀態(tài)更新時(shí),不需要通知所有觀察者進(jìn)行狀態(tài)更新寇漫,而是只需要關(guān)注它的狀態(tài)更新的觀察者才需要接到通知刊殉。
觀察者
我們先來(lái)定義觀察者的邏輯,這里通過(guò)泛型州胳,來(lái)定義觀察者只關(guān)注具體的被觀察者的實(shí)現(xiàn)记焊。
import lombok.Data;
@Data
public class Observer<T extends Subject>{
private String name;
private T subject;
public Observer (String name, T subject) {
this.name = name;
this.subject = subject;
subject.addObserver(this);
}
public void onMessage() {
System.out.println(this.name + "監(jiān)聽(tīng)到事件");
}
}
被觀察者
被觀察的notifyObervers()方法,在通知觀察者進(jìn)行狀態(tài)更新時(shí)栓撞,只有該觀察者關(guān)注的是自己的實(shí)現(xiàn)時(shí)遍膜,才更新。
import java.util.ArrayList;
import java.util.List;
@Data
public class Subject {
private List<Observer> observers = new ArrayList<Observer>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void update(){
notifyObervers();
}
public void notifyObervers(){
for (Observer observer: observers) {
if (observer.getSubject().getClass() == this.getClass()) {
observer.onMessage();
}
}
}
}
我們這里定義兩個(gè)被觀察者的實(shí)現(xiàn)類(lèi)瓤湘。
public class FirstSubject extends Subject {}
public class SecondSubject extends Subject {}
客戶端
這里客戶端的使用代碼為,實(shí)例化了一個(gè)FirstSubject對(duì)象和一個(gè)SecondSubject瓢颅。和兩個(gè)Observer對(duì)象,他們都只關(guān)注各自的Subject弛说。在把secondObserver也加到firstSubject對(duì)象的觀察者集合里面挽懦,這時(shí)
public class App {
public static void main(String[] args) {
Subject firstSubject = new FirstSubject();
Subject secondSubject = new SecondSubject();
Observer<FirstSubject> firstObserver = new Observer<FirstSubject>("firstObserver", (FirstSubject) firstSubject);
Observer<SecondSubject> secondObserver = new Observer<SecondSubject>("secondObserver", (SecondSubject) secondSubject);
firstSubject.addObserver(secondObserver);
firstSubject.update();
}
}
輸出
firstObserver監(jiān)聽(tīng)到事件
這樣就實(shí)現(xiàn)了一個(gè)泛型類(lèi)的觀察者,這里的實(shí)現(xiàn)感覺(jué)有些蹩腳木人,還需要看看別人時(shí)怎么實(shí)現(xiàn)的信柿。