成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Java 設(shè)計(jì)模式 觀察者模式

馬忠志 / 402人閱讀

摘要:實(shí)際上,設(shè)計(jì)模式就是通過(guò)面向?qū)ο蟮奶匦?,將這些角色解耦觀察者模式本質(zhì)上就是一種訂閱發(fā)布的模型,從邏輯上來(lái)說(shuō)就是一對(duì)多的依賴(lài)關(guān)系。在添加一個(gè)觀察者時(shí),把被主題被觀察者對(duì)象以構(gòu)造函數(shù)的形式給傳入了觀察者。

每個(gè)角色都對(duì)應(yīng)這一個(gè)類(lèi),比如觀察者模式,觀察者對(duì)應(yīng)著觀察者類(lèi),被觀察者對(duì)應(yīng)著被觀察者類(lèi)。實(shí)際上,設(shè)計(jì)模式就是通過(guò)面向?qū)ο蟮奶匦裕瑢⑦@些角色解耦

觀察者模式本質(zhì)上就是一種訂閱 / 發(fā)布的模型,從邏輯上來(lái)說(shuō)就是一對(duì)多的依賴(lài)關(guān)系。什么意思呢?好比是一群守衛(wèi)盯著一個(gè)囚犯,只要囚犯一有異動(dòng),守衛(wèi)就必須馬上采取行動(dòng)(也有可能是更新?tīng)顟B(tài),本質(zhì)上也是一種行動(dòng)),那么守衛(wèi)就是觀察者,囚犯就是被觀察者

在一個(gè)系統(tǒng)中,實(shí)現(xiàn)這種一對(duì)多的而且之間有一定關(guān)聯(lián)的邏輯的時(shí)候,由于需要保持他們之間的協(xié)同關(guān)系,所以最簡(jiǎn)便的方法是采用緊耦合,把這些對(duì)象綁定到一起。但是這樣一來(lái),一旦有擴(kuò)展或者修改的時(shí)候,開(kāi)發(fā)人員所面對(duì)的難度非常大,而且很容易造成Bug。那么觀察者模式就解決了這么一個(gè)問(wèn)題,在保持一系列觀察者和被觀察者對(duì)象協(xié)同工作的同時(shí),把解耦了它們

Coding

抽象觀察者角色類(lèi)

public interface Observer 
{
    // 更新接口
    public void update();
}

具體觀察者角色類(lèi)

public class ConcreteObserver implements Observer 
{
    // 觀察者的狀態(tài)
    private String observerState = "Initial";     // 觀察者初始狀態(tài),會(huì)隨著被觀察者變化而變化
    private String name;                         // 觀察者名稱(chēng),用于標(biāo)記不同觀察者
    private Subject concreteSubject;
    
    // 構(gòu)造觀察者,并傳入被主題對(duì)象,以及標(biāo)識(shí)該觀察者名稱(chēng)
    public ConcreteObserver(Subject concreteSubject, String name)
    {
        this.concreteSubject = concreteSubject;
        this.name = name;
        System.out.println("我是觀察者" + name +", 我的狀態(tài)是" + observerState);
    }
    
    // 觀察者狀態(tài)隨主題主題改變
    public void update() 
    {
        observerState = concreteSubject.SubjectState;
        System.out.println("我是觀察者" + name +", 我的狀態(tài)是" + observerState);
    }
}

抽象主題角色類(lèi)

import java.util.List;

public abstract class Subject 
{
    // 用來(lái)保存注冊(cè)的觀察者對(duì)象
    List list = null;
    String SubjectState;
    
    // 注冊(cè)觀察者對(duì)象
    public void attach(Observer observer){};
    
    //刪除觀察者對(duì)象
    public void detach(Observer observer){};
    
    // 通知所有注冊(cè)的觀察者對(duì)象
    public void nodifyObservers(String newState){};
}

具體主題角色類(lèi)

import java.util.ArrayList;
import java.util.List;

public class ConcreteSubject extends Subject
{
    private List list = new ArrayList();
    public String SubjectState;


    // 注冊(cè)觀察者對(duì)象
    public void attach(Observer observer)
    {
        list.add(observer);
        System.out.println("Attached an observer");
    }
    
    //刪除觀察者對(duì)象
    public void detach(Observer observer){
        
        list.remove(observer);
    }
    
    // 通知所有注冊(cè)的觀察者對(duì)象
    public void nodifyObservers(String newState)
    {
        for(Observer observer : list)
        {
            observer.update();
        }
    }
}

客戶(hù)端

public class Client 
{
    public static void main(String[] args) 
    {
        // 創(chuàng)建主題對(duì)象
        Subject concreteSubject = new ConcreteSubject();
        concreteSubject.attach(new ConcreteObserver(concreteSubject, "安倍晴明"));
        concreteSubject.attach(new ConcreteObserver(concreteSubject, "神樂(lè)"));
        concreteSubject.attach(new ConcreteObserver(concreteSubject, "源博雅"));
        
        concreteSubject.SubjectState = "結(jié)界突破!";
        concreteSubject.nodifyObservers(concreteSubject.SubjectState);
    }
}

運(yùn)行結(jié)果

我是觀察者安倍晴明, 我的狀態(tài)是Initial
Attached an observer
我是觀察者神樂(lè), 我的狀態(tài)是Initial
Attached an observer
我是觀察者源博雅, 我的狀態(tài)是Initial
Attached an observer
我是觀察者安倍晴明, 我的狀態(tài)是結(jié)界突破!
我是觀察者神樂(lè), 我的狀態(tài)是結(jié)界突破!
我是觀察者源博雅, 我的狀態(tài)是結(jié)界突破!

觀察者模式關(guān)鍵點(diǎn)

在主題(被觀察者)中,定義了一個(gè)集合用來(lái)存放觀察者,編寫(xiě)了注冊(cè)attach()和移除detach()觀察者的方法,這體現(xiàn)了一對(duì)多的關(guān)系,也提供了可以控制觀察者的方式
關(guān)鍵點(diǎn)1:每個(gè)觀察者需要被保存到主題(被觀察者)的集合中,并且被觀察者提供添加和刪除的方式

觀察者和被觀察者之間的交互活動(dòng)。在添加一個(gè)觀察者時(shí),把被主題(被觀察者)對(duì)象以構(gòu)造函數(shù)的形式給傳入了觀察者。最后主題(被觀察者)執(zhí)行nodifyObservers()方法,觸發(fā)所有觀察者的update()方法以更新?tīng)顟B(tài)
關(guān)鍵點(diǎn)2:被主題(被觀察者)把自己傳給觀察者,當(dāng)狀態(tài)改變后,通過(guò)遍歷或循環(huán)的方式逐個(gè)通知列表中的觀察者

但這里有個(gè)問(wèn)題,主題(被觀察者)是通過(guò)構(gòu)造函數(shù)參數(shù)的形式,傳給觀察者的,而觀察者對(duì)象時(shí)被attach()到主題(被觀察者)的list中
關(guān)鍵點(diǎn)3:雖然解耦了觀察者和主題(被觀察者)的依賴(lài),讓各自的變化不大影響另一方的變化,但是這種解耦并不徹底,沒(méi)有完全解除兩者之間的耦合

關(guān)鍵點(diǎn)4:在事件中,訂閱者和發(fā)布者之間是通過(guò)把事件處理程序綁定到委托,并不是把自身傳給對(duì)方。所以解決了觀察者模式中不完全解耦的問(wèn)題

委托,事件,和觀察者模式之間的關(guān)系

觀察者模式,必然涉及到2委托和事件這兩種類(lèi)型

委托

委托就是可把方法當(dāng)做另一個(gè)方法參數(shù)來(lái)傳遞,需要注意方法簽名。委托可以看做是方法的抽象,也就是方法的“類(lèi)”,一個(gè)委托的實(shí)例可以是一個(gè)或者多個(gè)方法。我們可以通過(guò)+=或者-=把方法綁定到委托或者從委托移除

事件

事件是一種特殊的委托。首先事件也是委托,只是在聲明事件的時(shí)候,需要加上event,如果你用reflector去看一個(gè)事件,你會(huì)發(fā)現(xiàn)里面就3樣?xùn)|西,一個(gè)Add_xxxx方法,一個(gè)Remove_xxx方法,一個(gè)委托。和上面所定義主題(被觀察者)時(shí)的注冊(cè)attach()和移除detach()有些聯(lián)系

.Net事件機(jī)制

實(shí)際上.Net的事件機(jī)制就是觀察者模式的一種體現(xiàn),并且是利用委托來(lái)實(shí)現(xiàn)。本質(zhì)上事件就是一種訂閱-發(fā)布模型也就是觀察者模式,這種機(jī)制中包含2個(gè)角色,一個(gè)是發(fā)布者,一個(gè)是訂閱者。發(fā)布者類(lèi)也就類(lèi)似于主題(被觀察者),發(fā)布者類(lèi)包含事件和委托定義,以及其之間的關(guān)系,發(fā)布者類(lèi)的對(duì)象調(diào)用事件通知其他訂閱者。而訂閱者類(lèi)也就類(lèi)似于觀察者,觀察者接受事件,并且提供處理的邏輯。也就是說(shuō),訂閱者對(duì)象(觀察者)中的方法會(huì)綁定到發(fā)布者(被觀察者)對(duì)象的委托中,一旦發(fā)布者(被觀察者)中事件被調(diào)用,發(fā)布者(被觀察者)就會(huì)調(diào)用委托中綁定的訂閱者(觀察者)的處理邏輯或者說(shuō)是處理程序,這就是通過(guò)觀察者模式實(shí)現(xiàn)的事件

觀察者模式問(wèn)答

在普通的觀察者模式中,解耦并不徹底,那么在事件的發(fā)布訂閱模型中,解耦徹底嗎?為什么?

答案是肯定的。因?yàn)樵谑录?,訂閱者和發(fā)布者之間是通過(guò)把事件處理程序綁定到委托,并不是把自身傳給對(duì)方。所以解決了觀察者模式中不完全解耦的問(wèn)題

通過(guò)委托綁定方法來(lái)實(shí)現(xiàn)觀察者模式,會(huì)不會(huì)有什么隱患?

有的,通過(guò)+=去把方法綁定到委托,很容易忘記-=。如果只綁定不移除,這個(gè)方法會(huì)一直被引用。我們知道GC去回收的時(shí)候,只會(huì)處理沒(méi)有被引用的對(duì)象,只要是還被引用的對(duì)象時(shí)不會(huì)被回收掉的。所以如果在長(zhǎng)期不關(guān)閉的系統(tǒng)中(比如監(jiān)控系統(tǒng)),大量的代碼使用+=而不-=,運(yùn)行時(shí)間長(zhǎng)以后有可能會(huì)內(nèi)存溢出

事件,委托,觀察者模式之間的關(guān)系

委托是一種類(lèi)型,事件是一種特殊的委托,觀察者模式是一種設(shè)計(jì)模式,事件的機(jī)制是觀察者模式的一種實(shí)現(xiàn),其中訂閱者和發(fā)布者通過(guò)委托實(shí)現(xiàn)協(xié)同工作

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/66508.html

相關(guān)文章

  • Java 設(shè)計(jì)模式察者模式

    摘要:三內(nèi)置觀察者模式了解內(nèi)置觀察者模式包內(nèi)包含最基本的類(lèi)與接口,這和上面的接口與接口很類(lèi)似。根據(jù)具體的需求,如果內(nèi)置的觀察者模式不能滿(mǎn)設(shè)計(jì),那么我們可以像剛開(kāi)始那樣自己實(shí)現(xiàn)一套觀察者模式。參考資料設(shè)計(jì)模式 一、了解觀察者模式 1.1 什么是觀察者模式 觀察者模式定義了對(duì)象之間的一對(duì)多依賴(lài),這樣一來(lái),當(dāng)一個(gè)對(duì)象狀態(tài)改變時(shí),它的所有依賴(lài)者都會(huì)收到通知并自動(dòng)更新。 典型的問(wèn)題比如報(bào)社,只要你是他...

    jsummer 評(píng)論0 收藏0
  • Java設(shè)計(jì)模式察者模式

    摘要:觀察者模式的使用場(chǎng)景比如你微博關(guān)注了一個(gè)人,那么這個(gè)人發(fā)布的微博就會(huì)推送到你這。 Java設(shè)計(jì)模式之觀察者模式 一直想寫(xiě)一篇學(xué)習(xí)觀察者模式的總結(jié)沒(méi)有契機(jī),今天學(xué)習(xí)阻塞隊(duì)列的原理時(shí)候看到在實(shí)現(xiàn)生產(chǎn)者消費(fèi)者的時(shí)候用到了通知模式,就是所謂的觀察者模式,正好順便整理一下。 1. 簡(jiǎn)介 觀察者模式定義對(duì)象間的一種一對(duì)多的依賴(lài)關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴(lài)于它的對(duì)象都得到通知并被自動(dòng)更...

    haitiancoder 評(píng)論0 收藏0
  • 我的Java設(shè)計(jì)模式-察者模式

    摘要:為了幫助灰太狼擺脫被老婆平底鍋抽的悲劇,發(fā)起了解救灰太狼的行動(dòng),必須要知道觀察者模式。持有觀察者對(duì)象的集合。設(shè)計(jì)模式源碼下載 相信大家都有看過(guò)《喜洋洋與灰太狼》,說(shuō)的是灰太狼和羊族的斗爭(zhēng),而每次的結(jié)果都是灰太狼一飛沖天,伴隨著一句我還會(huì)回來(lái)的......。為灰太狼感到悲哀,抓不到羊,在家也被老婆平底鍋虐待。灰太狼為什么會(huì)這么背? 很簡(jiǎn)單,灰太狼本身就有暴露行蹤的屬性,羊咩咩就能知曉灰太...

    smartlion 評(píng)論0 收藏0
  • 自我理解-察者(Observer)模式

    摘要:觀察者模式觀察者模式也可以成為發(fā)布訂閱模式,此模式是對(duì)象之間的模式,對(duì)象之間呈現(xiàn)一種一對(duì)多的關(guān)系。其中的一是被觀察者,多是觀察者,故被觀察者不能產(chǎn)生多個(gè)對(duì)象,只能有一個(gè)對(duì)象供觀察者觀察,所以在寫(xiě)被觀察者的時(shí)候,需要使用到單例模式。 觀察者(Observer)模式 觀察者(Observer)模式 也可以成為發(fā)布訂閱模式,此模式是對(duì)象之間的模式,對(duì)象之間呈現(xiàn)一種一對(duì)多的關(guān)系。其中的一是被觀...

    xuweijian 評(píng)論0 收藏0
  • JAVA設(shè)計(jì)模式-察者模式

    摘要:觀察者模式涉及的角色主題一對(duì)多中的一,持有數(shù)據(jù),當(dāng)數(shù)據(jù)更新時(shí),通知已注冊(cè)的觀察者觀察者一對(duì)多中的多,接收主題數(shù)據(jù)做出響應(yīng)舉個(gè)栗子一位媽媽主題有兩個(gè)孩子,取名為小愛(ài)和小冰觀察者。 概念 觀察者模式:定義了對(duì)象之間的一對(duì)多依賴(lài),這樣一來(lái),當(dāng)一個(gè)對(duì)象狀態(tài)改變時(shí),他的所有依賴(lài)者都會(huì)收到通知并自動(dòng)更新。 showImg(https://segmentfault.com/img/bVbf0or?w...

    vvpale 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<