1. 程式人生 > >對觀察者模式的理解

對觀察者模式的理解

設計模式 觀察者模式 observer java

觀察者模式(Observer)

觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,讓它們能夠自動更新自己。


觀察者模式的組成

抽象主題角色 具體主題角色

抽象觀察者角色 具體觀察者角色


個人理解:

觀察者模式類似於一種廣播機制,當被觀察者的狀態發生改變時,會通知觀察者,從而根據被觀察者狀態做出響應。同時觀察者模式也是一種任務分發機制,觀察者就是任務的執行者。


觀察者模式的關鍵在於被觀察者內部維護著一個觀察者列表,被觀察者內有一個方法,當該方法被調用時,就會調用觀察者對應的方法。從表面上看,就像是這些方法被自動調用了一般。本質上則是被觀察者方法的調用。


Java裏的AWT是如何使用觀察者模式的?

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TestButton {
    public static void main(String[] args) {
        Frame frame = new Frame("Button");
        Button button = new Button("Click");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println(e.getActionCommand());
            }
        });
        frame.add(button, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }
}

這裏使用java.awt.Button這個組件來分析一下。

從觀察者模式的組成來看,這是一個具體主題角色。它有一個方法addActionListener(),接收一個實現ActionListener接口的類的實例,這個實例就是一個觀察者,這個方法就向被觀察者button註冊了一個監聽器(觀察者)。文檔中是這樣寫的:

When a button is pressed and released, AWT sends an instance of ActionEvent to the button, by calling processEvent on the button. The button‘s processEvent

method receives all events for the button; it passes an action event along by calling its own processActionEvent method. The latter method passes the action event on to any action listeners that have registered an interest in action events generated by this button.

翻譯過來就是:當在button上出現一個點擊事件,AWT就會生成一個ActionEvent的實例,並調用button的processEvent方法:

    protected void processEvent(AWTEvent e) {
        if (e instanceof ActionEvent) {
            processActionEvent((ActionEvent)e);
            return;
        }
        super.processEvent(e);
    }

這個方法對於單擊按鈕來說就會調用processActionEvent方法:

    protected void processActionEvent(ActionEvent e) {
        ActionListener listener = actionListener;
        if (listener != null) {
            listener.actionPerformed(e);
        }
    }

而processActionEvent最終會調用註冊到這個button上的actionListener上的actionPerformed方法,並將ActionEvent作為參數進行傳遞。這就是一次完整的方法調用過程。


不過看到這裏我還有個疑問,就是被觀察者內部會維護一個觀察者列表,當一個事件發生時被觀察者會調用所有已註冊觀察者的特定方法。但是Button的源碼裏只有這樣一句:

transient ActionListener actionListener;

也就是說從表面上看,Button類內部只維護著一個ActionListener接口的實例,那麽它究竟是如何實現添加多個觀察者,並調用它們的方法的呢?繼續跟進代碼:

    // Button.java
    public synchronized void addActionListener(ActionListener l) {
        if (l == null) {
            return;
        }
        actionListener = AWTEventMulticaster.add(actionListener, l);
        newEventsOnly = true;
    }
    
    // AWTEventMulticaster.java
    public static ActionListener add(ActionListener a, ActionListener b) {
        return (ActionListener)addInternal(a, b);
    }
    
    // AWTEventMulticaster.java
    protected static EventListener addInternal(EventListener a, EventListener b) {
        if (a == null)  return b;
        if (b == null)  return a;
        return new AWTEventMulticaster(a, b);
    }

這樣就清楚了,原來是通過AWTEventMulticaster這個類封裝了具體的actionListener信息,調用的時候遞歸調用就可以了。

    // AWTEventMulticaster.java
    public void actionPerformed(ActionEvent e) {
        ((ActionListener)a).actionPerformed(e);
        ((ActionListener)b).actionPerformed(e);
    }

以上就是Java AWT使用觀察者模式的原理

本文出自 “木葉的思考” 博客,請務必保留此出處http://muye12921.blog.51cto.com/5008231/1971128

對觀察者模式的理解