一、基礎簡介
1、定義
定義了一種一對多的依賴關(guān)系,讓多個觀察者對象同時監(jiān)聽某一個主題對象,當主題對象的狀態(tài)發(fā)生改變時,會通知所有觀察者對象,使他們能夠自動更新自己。觀察者模式屬于行為型模式。
2、使用場景
當一個對象的改變需要同時改變其他對象,而且它不知道具體有多少對象有待改變時(解耦),可以考慮使用觀察者模式。
3、優(yōu)缺點
優(yōu)點: 1、觀察者和被觀察者是抽象耦合的。 2、建立一套觸發(fā)機制。
缺點: 1、如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。 2、如果在觀察者和觀察目標之間有循環(huán)依賴的話,觀察目標會觸發(fā)它們之間進行循環(huán)調(diào)用,可能導致系統(tǒng)崩潰。 3、觀察者模式?jīng)]有相應的機制讓觀察者知道所觀察的目標對象是怎么發(fā)生變化的,而僅僅只是知道觀察目標發(fā)生了變化。
4、模式結(jié)構(gòu)
- 抽象主題(Subject)角色:也叫抽象目標類,它提供了一個用于保存觀察者對象的聚集類和增加、刪除觀察者對象的方法,以及通知所有觀察者的抽象方法。
- 具體主題(Concrete Subject)角色:也叫具體目標類,它實現(xiàn)抽象目標中的通知方法,當具體主題的內(nèi)部狀態(tài)發(fā)生改變時,通知所有注冊過的觀察者對象。
- 抽象觀察者(Observer)角色:它是一個抽象類或接口,它包含了一個更新自己的抽象方法,當接到具體主題的更改通知時被調(diào)用。
- 具體觀察者(Concrete Observer)角色:實現(xiàn)抽象觀察者中定義的抽象方法,以便在得到目標的更改通知時更新自身的狀態(tài)。
二、代碼實例
1、UML類圖
2、Subject 抽象目標類:通知者
package com.mfc.design.觀察者模式;
import java.util.ArrayList;
import java.util.List;
/**
* @author MouFangCai
* @date 2019/10/16 10:39
*
* 抽象通知者
*/
public class Subject {
private String subjectName;
private List<Observer> observers = new ArrayList<>();
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void notifyAllObserver(String newState){
for (Observer ob : observers) {
ob.update(newState );
}
}
public String getSubjectName() {
return subjectName;
}
public void setSubjectName(String subjectName) {
this.subjectName = subjectName;
}
}
3、ConcreteSubject 具體通知者
package com.mfc.design.觀察者模式;
/**
* @author MouFangCai
* @date 2019/10/16 10:44
*
* 具體通知者
*/
public class ConcreteSubject extends Subject {
private String state;
public ConcreteSubject(String name) {
setSubjectName(name);
}
public void change(String newState) {
this.state = state;
notifyAllObserver(newState);
}
}
4、Observer:抽象觀察者
package com.mfc.design.觀察者模式;
/**
* @author MouFangCai
* @date 2019/10/16 10:33
*
* 抽象觀察者
*/
public abstract class Observer {
private String name;
private Subject subject;
abstract void update(String newState);
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
}
5、ConcreteObserver:具體觀察者
package com.mfc.design.觀察者模式;
/**
* @author MouFangCai
* @date 2019/10/16 10:36
*
* 具體觀察者
*/
public class ConcreteObserver1 extends Observer {
public ConcreteObserver1(String name, Subject subject) {
this.setName(name);
this.setSubject(subject);
}
@Override
public void update(String newState) {
System.out.println("觀察者:" + this.getName() + "——收到[" + this.getSubject().getSubjectName() + "]通知{"+newState +"},改變狀態(tài)");
}
}
package com.mfc.design.觀察者模式;
/**
* @author MouFangCai
* @date 2019/10/16 10:36
*
* 具體觀察者
*/
public class ConcreteObserver2 extends Observer {
public ConcreteObserver2(String name, Subject subject) {
this.setName(name);
this.setSubject(subject);
}
@Override
public void update(String newState) {
System.out.println("觀察者:" + this.getName() + "——收到[" + this.getSubject().getSubjectName() + "]通知{"+newState +"},改變狀態(tài)");
}
}
6、客戶端測試
package com.mfc.design.觀察者模式;
/**
* @author MouFangCai
* @date 2019/10/16 14:09
*/
public class Client_Observer {
public static void main(String[] args) {
Subject subject = new ConcreteSubject("通知者");
ConcreteObserver1 observer1 = new ConcreteObserver1("觀察者1", subject);
ConcreteObserver2 observer2 = new ConcreteObserver2("觀察者2", subject);
subject.attach(observer2);
subject.attach(observer1);
subject.notifyAllObserver("消息來了");
}
}
7、結(jié)果分析
觀察者:觀察者2——收到[通知者]通知{消息來了},改變狀態(tài)
觀察者:觀察者1——收到[通知者]通知{消息來了},改變狀態(tài)Process finished with exit code 0
對于“觀察者模式”簡單理解就是:放風,一個哨兵(Subject)觀察情況,發(fā)現(xiàn)情況就“按鈴”通知,具體通知哪些,哨兵也不知道,只有時刻關(guān)注“鈴鐺”的觀察者(ConcreteObserver)才會收到消息,做出相應的改變