JAVA的觀察者模式的作用是什么

今天就跟大家聊聊有關(guān)JAVA的觀察者模式的作用是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

創(chuàng)新互聯(lián)公司作為成都網(wǎng)站建設(shè)公司,專(zhuān)注網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì),有關(guān)成都定制網(wǎng)站方案、改版、費(fèi)用等問(wèn)題,行業(yè)涉及社區(qū)文化墻等多個(gè)領(lǐng)域,已為上千家企業(yè)服務(wù),得到了客戶(hù)的尊重與認(rèn)可。

    當(dāng)對(duì)象間存在一對(duì)多關(guān)系時(shí),則使用觀察者模式(Observer Pattern)。比如,當(dāng)一個(gè)對(duì)象被修改時(shí),則會(huì)自動(dòng)通知它的依賴(lài)對(duì)象。觀察者模式屬于行為型模式。觀察者模式是Java非常重要的一個(gè)設(shè)計(jì)模式。

觀察者模式所涉及的角色有:

●  抽象主題(Subject)角色:抽象主題角色把所有對(duì)觀察者對(duì)象的引用保存在一個(gè)聚集(比如ArrayList對(duì)象)里,每個(gè)主題都可以有任何數(shù)量的觀察者。抽象主題提供一個(gè)接口,可以增加和刪除觀察者對(duì)象,抽象主題角色又叫做抽象被觀察者(Observable)角色。

●  具體主題(ConcreteSubject)角色:將有關(guān)狀態(tài)存入具體觀察者對(duì)象;在具體主題的內(nèi)部狀態(tài)改變時(shí),給所有登記過(guò)的觀察者發(fā)出通知。具體主題角色又叫做具體被觀察者(Concrete Observable)角色。

●  抽象觀察者(Observer)角色:為所有的具體觀察者定義一個(gè)接口,在得到主題的通知時(shí)更新自己,這個(gè)接口叫做更新接口。

●  具體觀察者(ConcreteObserver)角色:存儲(chǔ)與主題的狀態(tài)自恰的狀態(tài)。具體觀察者角色實(shí)現(xiàn)抽象觀察者角色所要求的更新接口,以便使本身的狀態(tài)與主題的狀態(tài) 像協(xié)調(diào)。如果需要,具體觀察者角色可以保持一個(gè)指向具體主題對(duì)象的引用。

抽象主題(subject)角色:

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

public abstract class Subject {

    private List<MyObserver>list = new ArrayList<>();

    public void register(MyObserver myObserver){
        if (!list.contains(myObserver)){
            list.add(myObserver);
        }
    }

    public void remove(MyObserver myObserver){
        if (list.contains(myObserver)){
            list.remove(myObserver);
        }
    }

    public void notifyObserver(){
        for (MyObserver myObserver : list) {
            myObserver.update();
        }
    }


}

抽象觀察者角色:

public interface MyObserver {

    void update();
}

具體主題角色:

public class Repoter extends Subject {

    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
        if (change()) {
            notifyObserver();
        }
    }

    public Boolean change() {
        if (msg.equals(getMsg())) {
            return true;
        } else {
            return false;
        }
    }
}

第一個(gè)具體觀察者對(duì)象:

public class PeopleDaily implements MyObserver {

    private Subject subject;

    public PeopleDaily(Subject subject) {
        this.subject = subject;
        subject.register(this);
    }

    @Override
    public void update() {
        System.out.println("人民日?qǐng)?bào)發(fā)布最新報(bào)道:" + ((Repoter) subject).getMsg());
    }

    public void remove() {
        subject.remove(this);
    }
}

第二個(gè)具體觀察者對(duì)象:

public class NewsFeeds implements MyObserver {

    private Subject subject;

    public NewsFeeds(Subject subject) {
        this.subject = subject;
        subject.register(this);
    }

    @Override
    public void update() {
        System.out.println("新聞聯(lián)播發(fā)布最新報(bào)道:" + ((Repoter) subject).getMsg());
    }

    public void remove() {
        subject.remove(this);
    }
}

第三個(gè)具體觀察者對(duì)象:

public class XinHuaNewsAgency implements MyObserver {
    private Subject subject;

    public XinHuaNewsAgency(Subject subject) {
        this.subject = subject;
        subject.register(this);
    }

    @Override
    public void update() {
        System.out.println("新華社發(fā)布最新報(bào)道:" + ((Repoter) subject).getMsg());
    }

    public void remove() {
        subject.remove(this);
    }
}

測(cè)試:

public class TestDemo {

    @Test
    public void demo(){
        Repoter repoter = new Repoter();
        NewsFeeds newsFeeds = new NewsFeeds(repoter);
        XinHuaNewsAgency xinHuaNewsAgency = new XinHuaNewsAgency(repoter);
        PeopleDaily peopleDaily = new PeopleDaily(repoter);

        repoter.setMsg("為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗?。?!");

    }
}

結(jié)果:

新聞聯(lián)播發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗?。?!
新華社發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗!??!
人民日?qǐng)?bào)發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗!??!

Process finished with exit code 0

刪除一個(gè)觀察者再試:

public class TestDemo {

    @Test
    public void demo(){
        Repoter repoter = new Repoter();
        NewsFeeds newsFeeds = new NewsFeeds(repoter);
        XinHuaNewsAgency xinHuaNewsAgency = new XinHuaNewsAgency(repoter);
        PeopleDaily peopleDaily = new PeopleDaily(repoter);

        repoter.setMsg("為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗!??!");
        repoter.remove(xinHuaNewsAgency);
        System.out.println("————————————————————————————————————————————————");
        repoter.setMsg("華為發(fā)布最新旗艦機(jī)Mate30系列型號(hào)手機(jī)");
    }
}

結(jié)果:

新聞聯(lián)播發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗?。?!
新華社發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗?。?!
人民日?qǐng)?bào)發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗?。?!
————————————————————————————————————————————————
新聞聯(lián)播發(fā)布最新報(bào)道:華為發(fā)布最新旗艦機(jī)Mate30系列型號(hào)手機(jī)
人民日?qǐng)?bào)發(fā)布最新報(bào)道:華為發(fā)布最新旗艦機(jī)Mate30系列型號(hào)手機(jī)

Process finished with exit code 0

對(duì)于觀察者模式,JDK已經(jīng)為我們提供了對(duì)應(yīng)的接口和類(lèi)。

JDK源代碼:

package java.util;

/**
 * 
 * 當(dāng)一個(gè)類(lèi)想要被告知可觀察對(duì)象的變化時(shí),它可以實(shí)現(xiàn) Observer 接口。
 * @author  Chris Warth
 * @see     java.util.Observable
 * @since   JDK1.0
 */
public interface Observer {
    /**
     * 
     * 每當(dāng)觀察對(duì)象發(fā)生變化時(shí),都會(huì)調(diào)用此方法。應(yīng)用程序調(diào)用 Observable 對(duì)象的 notifyObservers 方法,以便讓所有對(duì) 
     * 象的觀察者收到更改通知。
     * @param   o     the observable object.
     * @param   arg   an argument passed to the <code>notifyObservers</code>
     *                 method.
     */
    void update(Observable o, Object arg);
}

Observer是一個(gè)接口,只是一個(gè)方法update用于接收通知者的通知并做出相應(yīng),具體的邏輯肯定是需要開(kāi)發(fā)者自己實(shí)現(xiàn)的了。

被觀察者,JDK的源碼如下:

package java.util;

/**
 * 
 * 此類(lèi)表示可觀察對(duì)象,或模型 - 視圖范例中的“數(shù)據(jù)”。它可以被子類(lèi)化以表示應(yīng)用程序想要觀察的對(duì)象。 
 * 可觀察對(duì)象可以有一個(gè)或多個(gè)觀察者。觀察者可以是實(shí)現(xiàn)接口 Observer 的任何對(duì)象。
 * 在可觀察的實(shí)例發(fā)生更改后,調(diào)用 Observable 的 notifyObservers 方法,應(yīng)用程序會(huì)通過(guò)調(diào)用 update 來(lái)通知所有觀察 
 * 者的更改。 
 * 未指定通知的遞送順序。 Observable類(lèi)中提供的默認(rèn)實(shí)現(xiàn)將按照它們注冊(cè)的順序通知Observers,但是子類(lèi)可能會(huì)更改此順 
 * 序,使用不保證順序,在單獨(dú)的線(xiàn)程上發(fā)送通知,或者可以保證它們的子類(lèi)遵循此順序,因?yàn)樗鼈冞x擇。 
 * 請(qǐng)注意,此通知機(jī)制與線(xiàn)程無(wú)關(guān),并且與類(lèi) Object 的 wait 和 notify 機(jī)制完全分開(kāi)。 
 * 當(dāng)新創(chuàng)建可觀察對(duì)象時(shí),其觀察者集合為空。當(dāng)且僅當(dāng) equals 方法為它們返回true時(shí),才認(rèn)為兩個(gè)觀察者是相同的。
 * @author  Chris Warth
 * @see     java.util.Observable#notifyObservers()
 * @see     java.util.Observable#notifyObservers(java.lang.Object)
 * @see     java.util.Observer
 * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
 * @since   JDK1.0
 */
public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs;

    //構(gòu)造方法
    public Observable() {
        obs = new Vector<>();
    }

    /**
     * 將觀察者添加到此對(duì)象的觀察者集中,前提是它與集合中已有的某個(gè)觀察者不同。未指定將通知發(fā)送給多個(gè)觀察者的順序。
     * @param   o   an observer to be added.
     * @throws NullPointerException   if the parameter o is null.
     */
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    /**
     * 
     * 從該對(duì)象的觀察者集中刪除觀察者。將 null 傳遞給此方法將不起作用。
     * @param   o   the observer to be deleted.
     */
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    /**
     * 
     * 如果此對(duì)象已更改,如 hasChanged 方法所示,則通知其所有觀察者,然后調(diào)用 clearChanged 方法以指示此對(duì)象不再 
     * 更改。 
     * 每個(gè)觀察者都使用兩個(gè)參數(shù)調(diào)用 update 方法:observable對(duì)象和 null 。換句話(huà)說(shuō),此方法等效于: 
     * notifyObservers(null)
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#hasChanged()
     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    public void notifyObservers() {
        notifyObservers(null);
    }

    /**
     * 
     * 如果此對(duì)象已更改,如 hasChanged 方法所示,則通知其所有觀察者,然后調(diào)用 clearChanged 方法以指示此對(duì)象不再 
     * 更改。 
     * 每個(gè)觀察者都使用兩個(gè)參數(shù)調(diào)用 update 方法:observable對(duì)象和 arg 參數(shù)。
     * @param   arg   any object.
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#hasChanged()
     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
     */
    public void notifyObservers(Object arg) {
        /*
         * 
         * 臨時(shí)數(shù)組緩沖區(qū),用作當(dāng)前Observers狀態(tài)的快照。
         */
        Object[] arrLocal;

        synchronized (this) {
            /* 
             * 我們不希望Observer在擁有自己的Monitor時(shí)進(jìn)行任意代碼的回調(diào)。我們從Vector中提取每個(gè)Observable并存 
             * 儲(chǔ)Observer狀態(tài)的代碼需要同步,但是通知觀察者不會(huì)(不應(yīng)該)。這里任何潛在競(jìng)爭(zhēng)條件的最壞結(jié)果是:
             * 1)新添加的觀察者將錯(cuò)過(guò)正在進(jìn)行的通知
             * 2)最近未注冊(cè)的觀察者將被錯(cuò)誤地通知
             */
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    /**
     * 
     * 清除觀察者列表,以便此對(duì)象不再具有任何觀察者。
     */
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    /**
     * 
     * 將此 Observable 對(duì)象標(biāo)記為已更改;  hasChanged 方法現(xiàn)在將返回 true 。
     */
    protected synchronized void setChanged() {
        changed = true;
    }

    /**
     * 
     * 表示此對(duì)象已不再更改,或者已向其所有觀察者通知其最近的更改,因此 hasChanged 方法現(xiàn)在將返回 false 。
     * 此方法由 notifyObservers 方法自動(dòng)調(diào)用。
     * @see     java.util.Observable#notifyObservers()
     * @see     java.util.Observable#notifyObservers(java.lang.Object)
     */
    protected synchronized void clearChanged() {
        changed = false;
    }

    /**
     * 
     * 測(cè)試此對(duì)象是否已更改。
     * @return  <code>true</code> if and only if the <code>setChanged</code>
     *          method has been called more recently than the
     *          <code>clearChanged</code> method on this object;
     *          <code>false</code> otherwise.
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#setChanged()
     */
    public synchronized boolean hasChanged() {
        return changed;
    }

    /**
     * 
     * 返回此 Observable 對(duì)象的觀察者數(shù)。
     * @return  the number of observers of this object.
     */
    public synchronized int countObservers() {
        return obs.size();
    }
}

Java源碼使用Vector,Vector相比于ArrayList來(lái)說(shuō),它是線(xiàn)程安全的。在添加和刪除觀察者時(shí)對(duì)兩個(gè)方法使用了synchronized關(guān)鍵字,這都是在為多線(xiàn)程考慮。

觀察者:實(shí)現(xiàn)觀察者接口(java.util.Observer),然后調(diào)用任何Observable對(duì)象的addObserver()方法,注銷(xiāo)觀察者時(shí),就調(diào)用deleteObserver()方法即可。

第一個(gè)觀察者對(duì)象:

public class XinhuaNewsAgency implements Observer {

    //被觀察者對(duì)象
    private Observable observable;

    public XinhuaNewsAgency(Observable observable) {
        this.observable = observable;
        //將觀察者對(duì)象加入到觀察者集合中
        observable.addObserver(this);

    }

    @Override
    public void update(Observable o, Object arg) {

        if(o instanceof Repoter){
            System.out.println("新華社發(fā)布最新報(bào)道:" + ((Repoter) o).getMsg());
        }
    }

    public void remove(){
        //刪除觀察者
        observable.deleteObserver(this);
    }
}

第二個(gè)觀察者對(duì)象:

public class PeopleDaily implements Observer {
    
    //被觀察者對(duì)象
    private Observable observable;

    public PeopleDaily(Observable observable) {
        this.observable = observable;
        //將觀察者對(duì)象加入到觀察者集合中
        observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {

        if (o instanceof Repoter){
            System.out.println("人民日?qǐng)?bào)發(fā)布最新報(bào)道:" + ((Repoter) o).getMsg());
        }
    }

    public void remove(){
        //刪除觀察者
        observable.deleteObserver(this);
    }
}

第三個(gè)觀察者對(duì)象:

public class NewsFeeds implements Observer {

    //被觀察對(duì)象
    private Observable observable;

    public NewsFeeds(Observable observable) {
        this.observable = observable;
        //將觀察者對(duì)象加入到觀察者集合中
        observable.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {

        if (o instanceof Repoter){
            System.out.println("新聞聯(lián)播發(fā)布最新報(bào)道:" + ((Repoter) o).getMsg());
        }

    }

    public void remove(){
        //刪除觀察者
        observable.deleteObserver(this);
    }
}

被觀察者:繼承java.util.Observable類(lèi),調(diào)用setChanged()方法,標(biāo)記狀態(tài)改變。然后調(diào)用nofityObservers()方法或者notifyobservers(Object arg) 方法。

public class Repoter extends Observable {

    private String msg;

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
        this.setChanged();
        this.notifyObservers(msg);
    }

}

測(cè)試:

public class TestDemo {

    @Test
    public void demo(){
        Repoter repoter = new Repoter();
        NewsFeeds newsFeeds = new NewsFeeds(repoter);
        PeopleDaily peopleDaily = new PeopleDaily(repoter);
        XinhuaNewsAgency xinhuaNewsAgency = new XinhuaNewsAgency(repoter);
        repoter.setMsg("為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗?。?!");
    }
}

結(jié)果:

新華社發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗!??!
人民日?qǐng)?bào)發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗!?。?
新聞聯(lián)播發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗?。?!

Process finished with exit code 0

結(jié)果發(fā)現(xiàn)順序和注冊(cè)的順序并不一致。將新聞聯(lián)播注銷(xiāo),在運(yùn)行:

public class TestDemo {

    @Test
    public void demo(){
        Repoter repoter = new Repoter();
        NewsFeeds newsFeeds = new NewsFeeds(repoter);
        PeopleDaily peopleDaily = new PeopleDaily(repoter);
        XinhuaNewsAgency xinhuaNewsAgency = new XinhuaNewsAgency(repoter);

        repoter.setMsg("為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗!?。?quot;);
        newsFeeds.remove();
        System.out.println("————————————————————————————————————————————————");
        repoter.setMsg("華為發(fā)布最新旗艦機(jī)Mate30系列型號(hào)手機(jī)");

    }
}

結(jié)果:

新華社發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗?。?!
人民日?qǐng)?bào)發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗?。?!
新聞聯(lián)播發(fā)布最新報(bào)道:為實(shí)現(xiàn)中華民族偉大復(fù)興而奮斗?。?!
————————————————————————————————————————————————
新華社發(fā)布最新報(bào)道:華為發(fā)布最新旗艦機(jī)Mate30系列型號(hào)手機(jī)
人民日?qǐng)?bào)發(fā)布最新報(bào)道:華為發(fā)布最新旗艦機(jī)Mate30系列型號(hào)手機(jī)

Process finished with exit code 0

劣勢(shì):

Observable是一個(gè)類(lèi),而不是一個(gè)接口,導(dǎo)致Observable類(lèi)的擴(kuò)展性不高,不如自己實(shí)現(xiàn)的觀察者模式靈活。
Observable將某些方法保護(hù)了起來(lái)(setChanged()和clearChanged()為protected),這意味著除非繼承自O(shè)bservable,否則將有關(guān)鍵的方法不能調(diào)用。導(dǎo)致無(wú)法通過(guò)組合的方式使其它類(lèi)獲得Observable類(lèi)的功能。

看完上述內(nèi)容,你們對(duì)JAVA的觀察者模式的作用是什么有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

網(wǎng)頁(yè)標(biāo)題:JAVA的觀察者模式的作用是什么
URL鏈接:http://www.muchs.cn/article42/ghjgec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、服務(wù)器托管、電子商務(wù)全網(wǎng)營(yíng)銷(xiāo)推廣、網(wǎng)站制作品牌網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司