Java設(shè)計(jì)模式中觀察者模式詳解
編程是一門藝術(shù),大批量的改動顯然是非常丑陋的做法,用心的琢磨寫的代碼讓它變的更美觀。
在現(xiàn)實(shí)世界中,許多對象并不是獨(dú)立存在的,其中一個對象的行為發(fā)生改變可能會導(dǎo)致一個或者多個其他對象的行為也發(fā)生改變。例如,某種商品的物價上漲時會導(dǎo)致部分商家高興,而消費(fèi)者傷心;還有,當(dāng)我們開車到交叉路口時,遇到紅燈會停,遇到綠燈會行。股票價格與股民、微信公眾號與微信用戶、天氣預(yù)報(bào)與聽眾等。
在軟件世界也是這樣,例如MVC 模式中的模型與視圖的關(guān)系;事件模型中的事件源與事件處理者。所有這些,如果用觀察者模式來實(shí)現(xiàn)就非常方便。
1.觀察者設(shè)計(jì)模式定義
觀察者(Observer)模式:指多個對象間存在一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。這種模式有時又稱作發(fā)布-訂閱模式、模型-視圖模式,它是對象行為型模式。
2.觀察者設(shè)計(jì)模式優(yōu)點(diǎn)與不足
觀察者模式是一種對象行為型模式,其主要優(yōu)點(diǎn):
- 降低了目標(biāo)與觀察者之間的耦合關(guān)系,兩者之間是抽象耦合關(guān)系。符合依賴倒置原則。
- 目標(biāo)與觀察者之間建立了一套觸發(fā)機(jī)制。
它的主要不足:
- 目標(biāo)與觀察者之間的依賴關(guān)系并沒有完全解除,而且有可能出現(xiàn)循環(huán)引用。
- 當(dāng)觀察者對象很多時,通知的發(fā)布會花費(fèi)很多時間,影響程序的效率。
3.觀察者設(shè)計(jì)模式實(shí)現(xiàn)思路
實(shí)現(xiàn)觀察者模式時要注意具體目標(biāo)對象和具體觀察者對象之間不能直接調(diào)用,否則將使兩者之間緊密耦合起來,這違反了面向?qū)ο蟮脑O(shè)計(jì)原則。
觀察者模式的主要角色如下。
- 抽象主題(Subject)角色:也叫抽象目標(biāo)類,它提供了一個用于保存觀察者對象的聚集類和增加、刪除觀察者對象的方法,以及通知所有觀察者的抽象方法。
- 具體主題(Concrete Subject)角色:也叫具體目標(biāo)類,它實(shí)現(xiàn)抽象目標(biāo)中的通知方法,當(dāng)具體主題的內(nèi)部狀態(tài)發(fā)生改變時,通知所有注冊過的觀察者對象。
- 抽象觀察者(Observer)角色:它是一個抽象類或接口,它包含了一個更新自己的抽象方法,當(dāng)接到具體主題的更改通知時被調(diào)用。
- 具體觀察者(Concrete Observer)角色:實(shí)現(xiàn)抽象觀察者中定義的抽象方法,以便在得到目標(biāo)的更改通知時更新自身的狀態(tài)。
4.觀察者設(shè)計(jì)模式應(yīng)用實(shí)例
/**
* 觀察者
*/
public interface Observer {
/**
* 更新
*/
void update();
}
/**
* 注意事項(xiàng) 被觀察者 被觀察者發(fā)出通知
*/
public abstract class Attentions {
/**
* 觀察者列表
*/
protected List<Observer> observers = new ArrayList();
/**
* 添加觀察者
* @param observer
*/
public void add(Observer observer) {
observers.add(observer);
}
/**
* 取消關(guān)注
* @param observer
*/
public void remove(Observer observer) {
observers.remove(observer);
}
/**
* 被觀察者發(fā)出通知 通知所有觀察者 觀察者可以做出相應(yīng)的行為
*/
public abstract void notifyObservers();
}
/**
* 觀察者 各種各樣的觀察者
*/
public class SoulMasterObserver implements Observer {
private String name;
public SoulMasterObserver(String name){
this.name = name;
}
/**
* 觀察者接收到通知做一些事情
*/
@Override
public void update() {
System.out.println(name + "收到作戰(zhàn)通知,趕往嘉陵關(guān)");
}
}
public class MangoAttention extends Attentions{
@Override
public void notifyObservers() {
//遍歷觀察者集合
for(Observer obs : observers) {
obs.update();
}
}
/*通知觀察者*/
public void perform(){
this.notifyObservers();
}
}
public class ObserverClient {
public static void main(String[] args) {
MangoAttention attentions = new MangoAttention();//目標(biāo)
attentions.add(new SoulMasterObserver("唐三"));
attentions.add(new SoulMasterObserver("馬紅俊"));
attentions.add(new SoulMasterObserver("小舞"));
attentions.add(new SoulMasterObserver("寧榮榮"));
attentions.perform();
}
}觀察者設(shè)計(jì)模式,首先需要定義一個觀察者的接口,這個接口定義了做什么一個行為,
然后定義一個被觀察者,這個里邊包含了一個觀察者的集合以及添加和刪除觀察者的方法以及一個通知的方法。
然后定義具體的觀察者,實(shí)現(xiàn)具體的行動,當(dāng)被通知之后就可以行動了。
具體的被觀察者實(shí)現(xiàn)通知的一個方法,遍歷所以的觀察者,通知觀察者執(zhí)行動作。
另外由于jkd本身提供了用于支持觀察者設(shè)計(jì)模式實(shí)現(xiàn)的兩個類,可以不用自己實(shí)現(xiàn)接口和抽象類,直接借助jdk提供的Observer和Obserable就可以,jdk提供的做的更好線程安全啥的都做了。
public class SoulMaster implements Observer {
private String name;
public SoulMaster(String name){
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(name + "收到作戰(zhàn)通知,趕往嘉陵關(guān)");
}
}
public class War extends Observable {
private String name;
public War(String name){
this.name = name;
}
public void perform(){
/*先設(shè)置改變*/
this.setChanged();
/*然后通知*/
this.notifyObservers();
}
}
public class JdkObserverClient {
public static void main(String[] args) {
War war = new War(":戰(zhàn)爭");
war.addObserver(new SoulMaster("唐三"));
war.addObserver(new SoulMaster("馬紅俊"));
war.addObserver(new SoulMaster("小舞"));
war.addObserver(new SoulMaster("寧榮榮"));
war.perform();
}
}可見通過jdk提供的兩個類實(shí)現(xiàn)觀察者,更加簡潔。
5.觀察者設(shè)計(jì)模式模式的應(yīng)用場景
在軟件系統(tǒng)中,當(dāng)系統(tǒng)一方行為依賴另一方行為的變動時,可使用觀察者模式松耦合聯(lián)動雙方,使得一方的變動可以通知到感興趣的另一方對象,從而讓另一方對象對此做出響應(yīng)。
觀察者模式適合以下幾種情形:
- 對象間存在一對多關(guān)系,一個對象的狀態(tài)發(fā)生改變會影響其他對象。
- 當(dāng)一個抽象模型有兩個方面,其中一個方面依賴于另一方面時,可將這二者封裝在獨(dú)立的對象中以使它們可以各自獨(dú)立地改變和復(fù)用。
- 實(shí)現(xiàn)類似廣播機(jī)制的功能,不需要知道具體收聽者,只需分發(fā)廣播,系統(tǒng)中感興趣的對象會自動接收該廣播。
- 多層級嵌套使用,形成一種鏈?zhǔn)接|發(fā)機(jī)制,使得事件具備跨域(跨越兩種觀察者類型)通知。
到此這篇關(guān)于Java設(shè)計(jì)模式中觀察者模式詳解的文章就介紹到這了,更多相關(guān)Java觀察者模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot 快速搭建微服務(wù)框架詳細(xì)教程
SpringBoot是為了簡化Spring應(yīng)用的創(chuàng)建、運(yùn)行、調(diào)試、部署等而出現(xiàn)的,使用它可以做到專注于Spring應(yīng)用的開發(fā),而無需過多關(guān)注XML的配置。本文重點(diǎn)給大家介紹Spring Boot 快速搭建微服務(wù)框架詳細(xì)教程,需要的的朋友參考下吧2017-09-09
Kotlin 內(nèi)聯(lián)函數(shù)詳解及實(shí)例
這篇文章主要介紹了Kotlin 內(nèi)聯(lián)函數(shù)詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-06-06
Java網(wǎng)絡(luò)通信基礎(chǔ)編程(必看篇)
下面小編就為大家?guī)硪黄狫ava網(wǎng)絡(luò)通信基礎(chǔ)編程(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05
Spring IOC:CreateBean環(huán)節(jié)中的流程轉(zhuǎn)換
Spring IOC 體系是一個很值得深入和研究的結(jié)構(gòu) , 只有自己真正的讀一遍 , 才能有更好的理解.這篇文章主要說明一下 CreateBean 整個環(huán)節(jié)中的大流程轉(zhuǎn)換 , 便于查找問題的原因2021-05-05

