程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> 觀察者模式

觀察者模式

編輯:JAVA編程入門知識

一、概念

  觀察者模式,又被稱為發布—訂閱模式、源—收聽者模式,是軟件設計模式的一種。在此種模式中,一個目標物件管理所有相依與它的觀察者物件,並且在它本身的狀態改變時主動發出同時,此種模式通常被用來實現事件處理系統。

二、觀察者模式組成

  觀察者模式一般包含以下四種角色:

  抽象主題角色Watched:把所有對觀察者對象的引用保存在一個集合中,每個抽象主題角色都可以有任意數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察這角色。

  抽象觀察者角色Watcher:為所有具體的觀察者定義一個接口,在得到主題的通知更新自己。

  具體主題角色ConcreteWatched:在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。

  具體觀察者角色ConcreteWatcher:該角色實現抽象觀察者角色所要求的更新接口,以便使自身的狀態與主題的狀態相協調。

三、觀察者模式實現方式

  觀察者模式有很多實現方式,從根本上說,該模式必須包含兩個角色,觀察者和被觀察對象。比較直觀的一種是使用“注冊”—“通知”—“撤銷通知”的形式。

  觀察者將自己注冊到被觀察對象中,被觀察者將觀察者放在一個容器中。

  被觀察者對象發生某種變化時,從容器中得到所有被注冊過的觀察者,將變化通知觀察者。

  觀察者將自己注冊到被觀察者的容器時,被觀察者不應該過問觀察者的具體類型,而是應該使用觀察者的接口。這樣的好處是:假定程序還有別的觀察者,那麼只要這個觀察者也是相同的接口即可。一個被觀察者可以對應多個觀察者,當被觀察者發生變化的時候,他可以將消息一一通知給所有的觀察者。如下圖所示:

  

  具體到一個應用場景就是:讀者訂閱新聞,每一個讀者都可以通過regist來訂閱新聞,通過remove來取消訂閱,當有新聞到來時,使用sendNews來通知每一位訂閱的讀者來收取新聞。

  下面用代碼來實現上面的實例:

  抽象主題角色Watched:新聞接口,定義訂閱、取消訂閱和推送新聞三個方法

public interface Watched
{
    //訂閱新聞
    void registeSubscriber(Watcher f_subscriber);
    //取消訂閱
    void removeSubscriber(Watcher f_subscriber);
    //推送新聞
    void sendNews();
}

  抽象觀察者角色Watcher:讀者接口,定義了獲取新聞的方法

public interface Watcher
{
    //獲取新聞
    void updateNews();
}

  具體主題角色ConcreteWatched,即被觀察者,實現了Watched接口:

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

/*
 * 具體被觀察者
 * 新聞發布者
 */
public class ConcreteWatched implements Watched
{
    private List<Watcher> subList=new ArrayList<Watcher>();
    @Override
    public void registeSubscriber(Watcher f_subscriber)
    {
        subList.add(f_subscriber);    
    }
    @Override
    public void removeSubscriber(Watcher f_subscriber)
    {
        subList.remove(f_subscriber);        
    }
    @Override
    public void sendNews()
    {
     System.out.println("開始本輪新聞推送!"); for (Watcher watcher : subList) { watcher.updateNews(); } System.out.println("本次新聞推送結束!"); } }

  具體觀察者角色ConcreteWatcher,即觀察者對象

/*
 * 具體的觀察者
 * 讀者
 */
public class ConcreteWatcher implements Watcher
{
    private String username;
        
    public ConcreteWatcher(String username)
    {
        super();
        this.username = username;
    }
    @Override
    public void updateNews()
    {
        System.out.println(username+"獲取到最新的新聞了!");
        
    }
}

  下面是一個測試用例:

import org.junit.Test;

public class WatchTest
{
    @Test
    public void test()
    {
        ConcreteWatched concreteWatched=new ConcreteWatched();
        Watcher watcher1=new ConcreteWatcher("讀者A");
        Watcher watcher2=new ConcreteWatcher("讀者B");
        Watcher watcher3=new ConcreteWatcher("讀者C");
        
        //訂閱新聞
        concreteWatched.registeSubscriber(watcher1);
        concreteWatched.registeSubscriber(watcher2);
        concreteWatched.registeSubscriber(watcher3);
        
        //推送新聞
        concreteWatched.sendNews();
        //讀者A取消訂閱
        concreteWatched.removeSubscriber(watcher1);

        //再次推送新聞
        concreteWatched.sendNews();
    }
}

  執行結果:

  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved