引用百度百科,觀察者模式概念:觀察者模式(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,很詳細