前言
Observer本來的意思是“觀察者”,但是實(shí)際上Observer角色并非主動(dòng)的去觀察痊剖,而是被動(dòng)的接收來自觀察對(duì)象角色的通知,因此找颓,Observer也被成為Publish-Subscribe(發(fā)布-訂閱)模式叮贩。它定義了一種一對(duì)多的依賴關(guān)系,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽某一個(gè)主題對(duì)象彪蓬。這個(gè)主題對(duì)象在狀態(tài)上發(fā)生變化時(shí)档冬,會(huì)通知所有觀察者對(duì)象桃纯,使它們能夠自動(dòng)更新自己。對(duì)于觀察者模式應(yīng)用的也很多呛牲,例如大家最熟悉的MVC框架就是觀察者模式的典型應(yīng)用娘扩,消息推送壮锻,事件監(jiān)聽等都是觀察者模式的最好詮釋。
在圖解設(shè)計(jì)模式中是通過一個(gè)觀察者觀察一個(gè)會(huì)生成數(shù)值的對(duì)象灰殴,并將生成的數(shù)值通過不同的觀察者顯示出來掰邢。照例通過如下UML類圖簡(jiǎn)單熟知下流程。
觀察者Observer
Observer角色負(fù)責(zé)接收來自觀察者對(duì)象角色的狀態(tài)變化的通知掰伸,它表示“觀察者”狮鸭,具體的觀察者會(huì)實(shí)現(xiàn)該接口,用于生成數(shù)字的觀察對(duì)象角色類NumberGenerator類會(huì)調(diào)用update方法并且將生成的數(shù)字變化的通知發(fā)送給Observer灾部。
public interface Observer {
public abstract void update(NumberGenerator generator);
}
觀察對(duì)象NumberGenerator
該類是用于生成數(shù)值的抽象類赌髓,提供了獲取數(shù)值和生成數(shù)值的抽象方法蒸痹,需要子類去實(shí)現(xiàn)叠荠。并且提供了一個(gè)存放觀察數(shù)值變化的觀察者對(duì)象的List扫责。方法addObserver(Observer observer)和deleteObserver(Observer observer)用注冊(cè)觀察者和刪除觀察者,重要的一步就是當(dāng)有數(shù)據(jù)變化時(shí)調(diào)用notifyObservers方法通知所有觀察者者娱。
public abstract class NumberGenerator {
private ArrayList observers=new ArrayList();
public void addObserver(Observer observer){
observers.add(observer);
}
public void deleteObserver(Observer observer){
observers.remove(observer);
}
public void notifyObservers(){
Iterator iterator=observers.iterator();
while (iterator.hasNext()){
Observer observer= (Observer) iterator.next();
observer.update(this);
}
}
public abstract int getNumber();
public abstract void execute();
}
具體的觀察對(duì)象RandomNumberGenerator
對(duì)于該具體觀察者對(duì)象黄鳍,它主要是用來生成隨機(jī)數(shù)框沟,并通過notifiObservers方法把每一次生成的結(jié)果通知給所有已注冊(cè)的觀察者
public class RandomNumberGenerator extends NumberGenerator {
private Random random = new Random();
private int number;
@Override
public int getNumber() {
return number;
}
@Override
public void execute() {
for (int i = 0; i < 5; i++){
number=random.nextInt(30);
notifyObservers();
}
}
}
具體觀察者
具體觀察者實(shí)現(xiàn)了觀察者Observer接口,當(dāng)update方法被調(diào)用時(shí)會(huì)去獲取要觀察的對(duì)象的最新數(shù)據(jù)忍燥,在此寫了兩個(gè)具體的觀察者梅垄。
public class DigitObserver implements Observer{
@Override
public void update(NumberGenerator generator) {
System.out.println("DigitObserver:"+generator.getNumber());
}
}
public class GraphObserver implements Observer{
@Override
public void update(NumberGenerator generator) {
System.out.println("GraphObserver:"+generator.getNumber());
}
}
測(cè)試類
public class Main {
public static void main(String[] args) {
NumberGenerator generator=new RandomNumberGenerator();
Observer observer1=new DigitObserver();
Observer observer2=new GraphObserver();
generator.addObserver(observer1);
generator.addObserver(observer2);
generator.execute();
}
}
輸出信息:
DigitObserver:2
GraphObserver:2
DigitObserver:19
GraphObserver:19
DigitObserver:26
GraphObserver:26
DigitObserver:10
GraphObserver:10
DigitObserver:14
GraphObserver:14
通過上面測(cè)試代碼队丝,你應(yīng)該發(fā)現(xiàn)對(duì)于觀察者對(duì)象可以有多個(gè)觀察者對(duì)其作出響應(yīng)欲鹏,如某些訂閱專欄,它可以被很多人訂閱吞加,當(dāng)專欄有內(nèi)容更新時(shí),它會(huì)給每一個(gè)人發(fā)送推送衔憨,我們?cè)谟嗛唽诤蠹迹⒉恍枰覀円恢比サ却膬?nèi)容更新,而不能去做自己的事情德崭。
好了揖盘,今天的觀察者模式到此結(jié)束。有問題歡迎留言指出憾股,Have a wonderful day .
如需文章中所寫代碼箕慧,請(qǐng)移步GitHub查看