當對象存在一對多關係時,則使用觀察者模式(observer pattern)。比如一個對象修改了,則會通知其所有依賴對象,此模式屬於行爲模式。
意圖:
定義對象見一對多的關係,當一個對象的狀態發生改變時,所有依賴它的對象都得到通知並自動更新。
主要解決:
一個對象改變給其他對象通知的問題,而且要考慮到易用和低耦合,保證高度協作。
何時使用:
一個對象(目標對象)的狀態發生改變,所有的依賴對象都得到通知,進行廣播通知。
如何解決:
使用面向對象技術,可以將這種依賴關係弱化。
關鍵代碼:
在抽象類有一個ArrayList存放觀察者們。
應用實例:
1.拍賣的時候,拍賣師觀察到最高價,通知給競價者。
優點:
觀察者和被觀察者是抽象耦合的,2.建立一套出發機制。
缺點:
1.如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者通知會話很長時間。2.如果在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發他們的循環調用,可能導致系統崩潰。3.觀察者模式沒有響應的機制讓觀察者知道所觀察的目標是怎樣發生變化的而僅僅知道觀察目標發生了變化。
使用場景:
一個抽象模型有兩個方面,其中一個方面依賴於另外一個方面,將這些方面封裝在獨立的對象中使它們獨自改變和使用;
一個對象的改變將導致其他一個或多個對象也發生改變,而不知道具體有多少對象將發生改變,可以降低對象的耦合度;
一個對象必須通知其他對象,而並不知道這些對象時誰;
需要在系統中創建一個觸發鏈,A對象的行爲將影響b,b->c,…可以使用觀察者模式創建一種鏈式觸發機制;
注意事項:
1.JAVA 中已經有了對觀察者模式的支持類;2.避免循環使用;3.如果順序執行,某一觀察者錯誤會導致阻塞,所以一般採用異步。
代碼:
被觀察者:其中通知的代碼寫在要更新的方法裏
package com.observer.beObservered;
import java.util.ArrayList;
import java.util.List;
public class Subject {
private List<Observer> observers = new ArrayList<>();
private int state;
public List<Observer> getObservers() {
return observers;
}
public void setObservers(List<Observer> observers) {
this.observers = observers;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyAllObservers();//通知方法
}
public void attach(Observer observer){
observers.add(observer);
}
public void notifyAllObservers(){
for(Observer o : observers){
o.update();
}
}
}
觀察者
抽象類
package com.observer.beObservered;
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
實現類
package com.obverser.obversers;
import com.observer.beObservered.Observer;
import com.observer.beObservered.Subject;
public class HexaObserver extends Observer{
public HexaObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("haxa:"+Integer.toHexString(this.subject.getState()));
}
}
package com.obverser.obversers;
import com.observer.beObservered.Observer;
import com.observer.beObservered.Subject;
public class OctalObserver extends Observer{
public OctalObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("octal:"+Integer.toOctalString(subject.getState()));
}
}
package com.obverser.obversers;
import com.observer.beObservered.Observer;
import com.observer.beObservered.Subject;
public class BinaryObserver extends Observer{
public BinaryObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("binary:"+Integer.toBinaryString(subject.getState()));
}
}
測試類
package com.observer.test;
import org.junit.Test;
import com.observer.beObservered.Subject;
import com.obverser.obversers.BinaryObserver;
import com.obverser.obversers.HexaObserver;
import com.obverser.obversers.OctalObserver;
public class TestDemo {
@Test
public void test(){
Subject subject = new Subject();
subject.setState(96);
new BinaryObserver(subject);
new HexaObserver(subject);
new OctalObserver(subject);
subject.setState(100);
}
}
控制檯打印
binary:1100000
haxa:60
octal:140
binary:1100100
haxa:64
octal:144