一、觀察者模式
當對象中存在一對多的關(guān)系時,就需要使用這種模式。比如說一個對象發(fā)生改變時,會通知到依賴它的對象。
介紹
- 意圖:定義對象之間一對多的依賴關(guān)系,當一個對象的狀態(tài)發(fā)生改變時,會通知到其它依賴該對象的行為。
- 主要解決:一個對象狀態(tài)改變給其他對象通知的問題,而且要考慮到易用和低耦合,保證高度的協(xié)作。
- 如何解決:采用面向?qū)ο蟮募夹g(shù),可以將這種關(guān)系弱化。
- 關(guān)鍵代碼:在被訂閱類里面采用一個集合來存放觀察者,并且在狀態(tài)改變時一一通知他們?nèi)ジ隆?/li>
- 應用實例:1.對于在訂閱了微信公眾號某個主題的用戶來說,每當公眾號有發(fā)布新的內(nèi)容時,會自動的將內(nèi)容及時推送到用戶;2.在初中的教室上課,當下課鈴聲響起的時候,學生們會主動收拾書包準備下課回家吃飯了;3.在某會議上面,領導召集了負責各個業(yè)務模塊的子領導,及時傳達了某些核心思想,參與了此次會議的小負責人會通知到各個下屬。
- 注意事項:1.Java中已經(jīng)有了對于觀察者的支持類。2.避免循環(huán)引用。3.如果順序執(zhí)行,某一個觀察者執(zhí)行時發(fā)生了錯誤,會導致卡克,一般采取異步的方式去執(zhí)行。
演示
下面通過一個小的demo來展示一下觀察者模式的使用場景。
-
微信公眾號推送文章
首先先來明確下各個扮演的角色,對于訂閱了某個公眾號的用戶來說,他們屬于觀察者,而公眾號的文章的發(fā)布屬于被觀察者。明確了這一點后,下面就比較好擼代碼了。
1、定義被觀察者的主要方法,采取接口來定義/** * 微信主題的接口 即被觀察著 他會有三個方法 * @author rain * */ public interface IWxServerSubject { void attach(IObserver observer); void detach(IObserver observer); void updateObserver(); }
2 、定義抽象的觀察者接口
/**
* 觀察者 訂閱了微信主題的觀察者
* @author rain
*
*/
public interface IObserver {
void receiveContent(String info);
}
`3、實現(xiàn)具體的被觀察者
public class IWxSubjectImpl implements IWxServerSubject{
//觀察者列表 訂閱了微信公眾號的讀者
private List<IObserver> observers = new ArrayList<>();
private String submitContent;
@Override
public void attach(IObserver observer) {
observers.add(observer);
}
//一個信號 即發(fā)布了新的文章
public void submitContent(String content){
this.submitContent = content;
updateObserver();
}
@Override
public void detach(IObserver observer) {
if(observers.contains(observer)){
observers.remove(observer);
}
}
@Override
public void updateObserver() {
for (IObserver iObserver : observers) {
iObserver.receiveContent(submitContent);
}
}
}
4、定義一個具體的觀察者
/**
* 讀者 訂閱了微信公眾號的 觀察者
* @author rain
*
*/
public class ReaderObsever implements IObserver{
private String name;
public ReaderObsever(String name) {
this.name = name;
}
@Override
public void receiveContent(String info) {
System.out.println(name +" ,請注意:Rain發(fā)布了新的微信公眾號文章---"+info);
}
public String getName(){
return name;
}
}
5、來個測試類模擬一下吧
public class Test {
public static void main(String[] args) {
IWxServerSubject subject = new IWxSubjectImpl();
//創(chuàng)建了四個讀者 并且都關(guān)注了該公眾號的 只有趙六沒有關(guān)注
ReaderObsever reader1 = new ReaderObsever("張三");
ReaderObsever reader2 = new ReaderObsever("李四");
ReaderObsever reader3 = new ReaderObsever("王五");
//訂閱了該公眾號的讀者 即觀察者角色
subject.attach(reader1);
subject.attach(reader2);
subject.attach(reader3);
//公眾號發(fā)布了文章了
((IWxSubjectImpl)subject).submitContent("觀察者設計模式開始啦!?。?);
}
}
運行一下:

模擬觀察者.png
可以看到,訂閱過該公眾號的用戶確實收到了新發(fā)布的文章,good。。。