java基礎(10)-----JDK中觀察者模式和事件驅動模型源碼解析

      引用百度百科,觀察者模式概念:觀察者模式(Observer)是軟件設計模式的一種,在此模式中,一個目標物件管理所有依附於它的所有觀察者物件,並且在它本身的狀態發生改變時主動發出通知。這通常通過呼叫觀察者實現的方法來實現,此種常被用來實現事件處理系統,例如事件驅動模型

1.JDK中的觀察者模式設計

用一個UML圖看下JDK提供了我們哪些接口和類:

Observer:觀察者。

Observerable:可觀察的,相當於Subject,被觀察者。

Observerable中使用布爾類型值changed標識被觀察者狀態是否改變,Vector作爲Observer觀察者容器,存放所有的觀察者對象;提供了一系列對觀察者對象的方法,添加、刪除、通知觀察者、觀察者對象計數。想要查看源碼的可以去JDK>rt.jar>java>util包下查看

案例

觀察者MyObserverA:

import java.util.Observable;
import java.util.Observer;

/**
 * 觀察者A
 * @author zisong yue
 * @date 2018-12-03
 */
public class MyObserverA implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("MyObserverA  update status");
    }
}

觀察者MyObserverB

import java.util.Observable;
import java.util.Observer;
/**
 * 觀察者B
 * @author zisong yue
 * @date 2018-12-03
 */
public class MyObserverB implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("MyObserverB update state");
    }
}

被觀察者MyObserverable

import java.util.Observable;
import java.util.Observer;

/**
 * 被觀察者
 * @author zisong yue
 * @date 2018-12-03
 */
public class MyObserverable extends Observable {
    @Override
    public synchronized void addObserver(Observer o) {
        super.addObserver(o);
    }

    @Override
    public void notifyObservers() {
        super.notifyObservers();
    }

    @Override
    protected synchronized void setChanged() {
        super.setChanged();
    }
}

測試類ObserverTest

/**
 * 測試類
 * @author zisong yue
 * @date 2018-12-03
 */
public class ObserverTest {
    public static void main(String[] args) {

        MyObserverable observerable = new MyObserverable();

        MyObserverA observerA = new MyObserverA();
        MyObserverB observerB = new MyObserverB();

        observerable.addObserver(observerA);
        observerable.addObserver(observerB);

        observerable.setChanged();
        observerable.notifyObservers();

    }
}

測試結果:

測試結果說明,當被觀察者對象MyObserverable狀態改變時,通知了所有已註冊的觀察者對象。

2.JDK中事件驅動模型設計

事件驅動模型一般包含以下幾個內容:

事件源:顧名思義,就是產生事件的地方

事件:具體的行爲

事件監聽器:針對事件做出相應的動作,可以在監聽器中處理一些業務邏輯

JDK中有個針對javaBean屬性的事件驅動,我們先看下怎麼用的,然後一起看下源碼怎麼實現的

Person類:

我們先看一個例子,然後再看下

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

/**
 * Person類是事件源
 * @author zisong yue
 * @date 2018-12-04
 */
public class Person{

    private PropertyChangeSupport changeSupport;

    private String name;

    private String sex;

    private int age;

    Person(){
        changeSupport = new PropertyChangeSupport(this);
        this.name = "張三";
        this.age = 13;
        this.sex = "男";
    }

    /**
     * 給所有屬性添加監聽器
     */
    public void addCommonListen(PropertyChangeListener changeListener){
        changeSupport.addPropertyChangeListener(changeListener);
    }
    /**
     * 給指定屬性添加監聽器
     */
    public void addNamedListen(String propertyName, PropertyChangeListener changeListener){
        changeSupport.addPropertyChangeListener(propertyName, changeListener);
    }

    public void setName(String name) {
        fireChange("name", this.name, name);
        this.name = name;
    }

    public void setSex(String sex) {
        fireChange("sex", this.sex, sex);
        this.sex = sex;
    }

    public void setAge(int age) {
        fireChange("age", this.age, age);
        this.age = age;
    }

    /**
     * 屬性值改變通知公共監聽器和指定屬性的監聽器
     */
    public void fireChange(String propertyName, Object oldValue, Object newValue){
        changeSupport.firePropertyChange(propertyName, oldValue, newValue);
    }

    public static void main(String[] args) {
        Person person = new Person();
        person.addCommonListen(new ListenerPropertyCommon());
        person.addNamedListen("name",new ListenerPropertyName());
        person.addNamedListen("age", new ListenerPropertyAge());
        person.addNamedListen("sex", new ListenerPropertySex());

        person.setName("張三2");
        person.setAge(14);
        person.setSex("女");

    }

}

各個屬性的監聽類和公共監聽類

所有屬性的監聽器(即可以監聽所有屬性的變化):

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

/**
 * 監聽所有屬性
 * @author zisong yue
 * @date 2018-12-05
 */
public class ListenerPropertyCommon implements PropertyChangeListener {
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println("ListenerPropertyCommon receive message, The PropertyName:" + evt.getPropertyName() + " is changed, oldValue:" + evt.getOldValue() +
                " newValue:" + evt.getNewValue());
    }
}

name屬性監聽器:

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

/**
 * name屬性監聽器
 * @author zisong yue
 * @date 2018-12-05
 */
public class ListenerPropertyName implements PropertyChangeListener{
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println("ListenerPropertyName receive message, The PropertyName:" + evt.getPropertyName() + " is changed, oldValue:" + evt.getOldValue() +
                " newValue:" + evt.getNewValue());
    }
}

age屬性監聽器:

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

/**
 * age屬性監聽器
 * @author zisong yue
 * @date 2018-12-05
 */
public class ListenerPropertyAge implements PropertyChangeListener{
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println("ListenerPropertyAge receive message, The PropertyName:" + evt.getPropertyName() + " is changed, oldValue:" + evt.getOldValue() +
        " newValue:" + evt.getNewValue());
    }
}

sex屬性監聽器:

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

/**
 * sex屬性監聽器
 * @author zisong yue
 * @date 2018-12-05
 */
public class ListenerPropertySex implements PropertyChangeListener{
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println("ListenerPropertySex receive message, The PropertyName:" + evt.getPropertyName() + " is changed, oldValue:" + evt.getOldValue() +
                " newValue:" + evt.getNewValue());
    }
}

執行Person中main方法,測試結果:

可以看到,Common監聽器對所有屬性的值的變化做出了相應,其他各自屬性的監聽器也做出了對應的相應

源碼分析:

PropertyChangeSupport:相當於事件源,裏面維護了一個PropertyChangeListenerMap(監聽器添加到這裏)

源碼挺簡單,就不再詳細的解釋了,有興趣的可去JDK的rt.jar    java>beans包下去看,都寫了JAVADOC,很詳細

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章