天天看點

設計模式一之觀察者模式

設計模式一之觀察者模式

1. 概念

觀察者模式(有時又被稱為釋出/訂閱模式)是軟體設計模式的一種。在此種模式中,一個目标物件管理所有相依于它的觀察者物件,并且在它本身的狀态改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實作。此種模式通常被用來實作事件處理系統。

上邊是比較官方的說發,個人了解這種模式就是一對多的監聽回調,比如老闆釋出QQ消息通知所有自己的員工某天放假,首先老闆手下的員工是不停變換的,有離職的有新加入的,是以老闆的員工是一對多的關系,而員工是不停變化的,所有員工通過加入老闆QQ群或離開QQ群和老闆建立關系或解除關系,老闆群裡釋出消息後所有注冊為自己的員工收到消息明天放假,不上班,每一個員工根據消息安排自己明天的事物。這就是一對多的關系。老闆和員工通過QQ群建立一對多的關系(QQ群隻是例子,預設隻有老闆能釋出消息,員工不能釋出消息,互不幹涉)。

2.代碼實作

以下是簡單的代碼實作,已員工和老闆為例,主要看注解。      
           
/**
 * 觀察者模式中“一”(被觀察者)的基礎接口
 * Created by 1 on 2016/4/23.
 */
public interface Observable {
     /**
      * 注冊觀察者
      * @param observe 
      */
     void registerObserver(Observe observe);

     /**
      * 移除觀察者
      * @param observe
      */
     void removeObserver(Observe observe);

     /**
      * 被觀察者狀态改變
      */
     void notifyObserver();
}
           
/**
 * 監察者基礎接口,每個監察者必須實作
 * Created by 1 on 2016/4/23.
 */
public interface Observe {
    /**
     * 可以有許多方法,觀察者接收到消息後處理
     * @param temp
     */
    void update(String temp);
}
           
/**
 * 老闆類(被觀察者,實作被觀察者接口)
 * Created by 1 on 2016/4/23.
 */
public class BossObservable implements Observable {

    //員工(監察者)清單
    private ArrayList<Observe> arrayListObserve;

    public BossObservable(){
        arrayListObserve = new ArrayList();
    }

    /**
     * 入職成為老闆員工(加入QQ群)
     * @param observe 要注冊的監察者
     */
    @Override
    public void registerObserver(Observe observe) {
        arrayListObserve.add(observe);
    }

    /**
     * 員工離職(離開QQ群)
     * @param observe
     */
    @Override
    public void removeObserver(Observe observe) {
        arrayListObserve.remove(observe);
    }

    /**
     * 老闆給所有員工發送消息(老闆在群裡釋出消息)
     */
    @Override
    public void notifyObserver() {
        for (int j = ;j < arrayListObserve.size();j++){
            arrayListObserve.get(j).update("明天放假");
        }
    }
}
           
/**
 * 第一個監察者(員工First)
 * 若新加監察者隻需實作接口
 * Created by 1 on 2016/4/23.
 */
public class FirstStaffObserve implements Observe{

    /**
     * 監測到老闆在QQ釋出放假消息
     * @param temp 放假消息
     */
    @Override
    public void update(String temp) {
        System.out.print("FirstStaff"+temp);
    }
}
           
/**
 * 第二個監察者(Second員工)
 * 若新加監察者隻需實作接口并且注冊成為監察者
 * Created by admin on 2016/4/23.
 */
public class SecondStaffObserve implements Observe{

    /**
     * 監測到老闆在QQ釋出放假消息
     * @param temp 放假消息
     */
    @Override
    public void update(String temp) {
        System.out.print("SecondStaff"+temp);
    }
}
           
//測試類
public class Test
{
    public static void main(String[] args)
    {
        BossObservable boss = new BossObservable();
        FirstStaffObserve firstStaffObserve = new FirstStaffObserve();
        SecondStaffObserve secondStaffObserve = new SecondStaffObserve();
        //注冊監察者(員工入職)
        boss.registerObserver(firstStaffObserve);
        boss.registerObserver(secondStaffObserve);
        //通知放假
        boss.notifyObserver();
        boss.removeObserver(firstStaffObserve);
    }
}
           

注:以上例子隻為了解監察者模式原理,若是真實使用,方法會傳入各種參數,以及多個方法,随自己使用而變化。

3.總結

觀察這模式使用場景:

一般button添加點選事件,對于某個事件發生改變做出監聽。一對多進行通知等。

觀察者模式的效果有以下的優點:

第一、觀察者模式在被觀察者和觀察者之間建立一個抽象的耦合。被觀察者角色所知道的隻是一個具體觀察者清單,每一個具體觀察者都符合一個抽象觀察者的接口。被觀察者并不認識任何一個具體觀察者,它隻知道它們都有一個共同的接口。

由于被觀察者和觀察者沒有緊密地耦合在一起,是以它們可以屬于不同的抽象化層次。如果被觀察者和觀察者都被扔到一起,那麼這個對象必然跨越抽象化和具體化層次。

第二、觀察者模式支援廣播通訊。被觀察者會向所有的登記過的觀察者發出通知。

觀察者模式有下面的缺點:

第一、如果一個被觀察者對象有很多的直接和間接的觀察者的話,将所有的觀察者都通知到會花費很多時間。

第二、如果在被觀察者之間有循環依賴的話,被觀察者會觸發它們之間進行循環調用,導緻系統崩潰。在使用觀察者模式是要特别注意這一點。

第三、如果對觀察者的通知是通過另外的線程進行異步投遞的話,系統必須保證投遞是以自恰的方式進行的。

第四、雖然觀察者模式可以随時使觀察者知道所觀察的對象發生了變化,但是觀察者模式沒有相應的機制使觀察者知道所觀察的對象是怎麼發生變化的,僅僅知道發生了什麼變化而已。