觀察者模式 一、什麼是觀察者模式? 觀察者模式(別名 發佈 訂閱)是軟體設計模式的一種。 觀察者模式屬於行為型模式 。(行為型模型 特別關註對象之間的通信) 觀察者模式(Observer)完美的將觀察者和被觀察的對象分離開。 觀察者設計模式定義了對象間 ...
觀察者模式
一、什麼是觀察者模式?
觀察者模式(別名--發佈-訂閱)是軟體設計模式的一種。觀察者模式屬於行為型模式。(行為型模型-特別關註對象之間的通信)
觀察者模式(Observer)完美的將觀察者和被觀察的對象分離開。觀察者設計模式定義了對象間的一種一對多的依賴關係,當一個對象的狀態發生變化時,所有依賴於它的對象都得到通知並自動更新。
易用和低耦合,保證高度的協作。
二、觀察者模式的適用場景
- 當一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。
- 當對一個對象的改變需要同時改變其它對象,而不知道具體有多少對象有待改變。
- 當一個對象必須通知其它對象,而它又不能假定其它對象是誰。換言之,你不希望這些對象是緊密耦合的。
三、觀察者模式的具體實現
結構圖
觀察者模式中的四個重要角色
- 抽象被觀察者角色(Observable):即一個抽象主題,它把所有對觀察者對象的引用保存在一個集合中,每個主題都可以有任意數量的觀察者。抽象主題提供一個添加和刪除觀察者角色的介面。一般用一個抽象類和介面來實現。
- 抽象觀察者角色(Observer):為所有的具體觀察者定義一個介面,在得到主題通知時更新自己。
- 具體被觀察者角色(ConcreteObservable):也就是一個具體的主題,當具體主題的內部狀態改變時,給所有登記過的觀察者發出通知。
- 具體觀察者角色(ConcreteObserver):實現抽象觀察者角色所要求的更新介面,以使其自身狀態和主題的狀態保持一致。
java代碼實現
1.定義一個抽象被觀察者介面,添加、刪除、通知觀察者
package com.designpattern.observerPattern;
/**
* 被觀察者介面 Observable
*
* @author zhongtao on 2018/9/10
*/
public interface Observable {
/**
* 添加觀察者
*/
void addObserver(Observer observer);
/**
* 移除觀察者
*/
void removeObserver(Observer observer);
/**
* 通知觀察者
*/
void notifyObserver();
}
2.定義一個抽象觀察者介面
package com.designpattern.observerPattern;
/**
* 觀察者介面 Observer
*
* @author zhongtao on 2018/9/10
*/
public interface Observer {
/**
* 更新消息
*/
void update(String message);
}
3.實現被觀察者,有一個List集合,用以保存註冊的觀察者,等需要通知觀察者時,遍歷該集合。
package com.designpattern.observerPattern;
import java.util.ArrayList;
import java.util.List;
/**
* 具體被觀察者
*
* @author zhongtao on 2018/9/10
*/
public class ConcreteObservable implements Observable {
// 用來存儲觀察者對象的集合
private List<Observer> list = new ArrayList<Observer>();
//消息
private String message;
@Override
public void addObserver(Observer observer) {
list.add(observer);
}
@Override
public void removeObserver(Observer observer) {
if(!list.isEmpty()) {
list.remove(observer);
}
}
@Override
public void notifyObserver() {
for (Observer observer : list) {
observer.update(message);
}
}
/**
* 設置更新消息
* @param message
*/
public void setNotifyMessage(String message){
this.message = message;
System.out.println("更新消息:" + message);
notifyObserver();
}
}
4.實現觀察者
package com.designpattern.observerPattern;
/**
* 具體實現觀察者
*
* @author zhongtao on 2018/9/10
*/
public class User implements Observer {
private String name;
public User(String name){
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + "你有新消息了:" + message);
}
}
5.測試觀察者模式
package com.designpattern.observerPattern;
import org.junit.Test;
/**
* 觀察者模式測試類
*
* @author zhongtao on 2018/9/10
*/
public class ObserverPatternTest {
/**
* 測試觀察者模式
*/
@Test
public void testObserverPattern() {
ConcreteObservable observable = new ConcreteObservable();
User peter = new User("Peter");
User make = new User("Make");
User lina = new User("Lina");
//添加觀察者
observable.addObserver(peter);
observable.addObserver(make);
observable.addObserver(lina);
observable.setNotifyMessage("星際爭霸2中人族太IMBA");
System.out.println("-----分割線-----");
observable.removeObserver(peter);
observable.setNotifyMessage("星靈才是最IMBA的!");
}
}
測試結果:當移除peter之後,peter就無法再收到推送消息了。
更新消息:星際爭霸2中人族太IMBA
Peter你有新消息了:星際爭霸2中人族太IMBA
Make你有新消息了:星際爭霸2中人族太IMBA
Lina你有新消息了:星際爭霸2中人族太IMBA
-----分割線-----
更新消息:星靈才是最IMBA的!
Make你有新消息了:星靈才是最IMBA的!
Lina你有新消息了:星靈才是最IMBA的!
四、觀察者模式的優缺點
優點:
- 觀察者和被觀察者是抽象耦合的。
- 建立一套觸發機制。
缺點:
- 如果一個被觀察者對象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會花費很多時間。
- 如果在觀察者和觀察目標之間有迴圈依賴的話,觀察目標會觸發它們之間進行迴圈調用,可能導致系統崩潰。
- 觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化。