天天看點

Tomcat中設計模式-觀察者模式

開篇

 觀察者模式的定義,有多個對象在關注着一個對象,如果這個對象的狀态發生了改變,其它依賴(關注)它的對象就會收到通知,然後在接收到通知以後各個對象做出相應的動作。

 觀察者模式涉及到兩個概念(觀察者和被觀察者),被觀察者隻能有一個,而觀察這個觀察者的對象可以用多個。【一對多】定義對象間的一種一對多的依賴關系。當一個對象的狀态發生改變時,所有依賴于它的對象都得到通知并被自動更新。

觀察者模式的demo

被觀察者

  • 1.被觀察者對象維護一個觀察者的清單對象和注冊觀察者的接口。
  • 2.事件發生變化時候周遊所有觀察者清單并觸發事件。
  • 3.觀察者統一實作某接口用以事件通知。
/***
 * 抽象被觀察者接口
 * 聲明了添加、删除、通知觀察者方法
 *
 */
public interface Observerable {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObserver();
    
}


/**
 * 被觀察者,也就是微信公衆号服務
 * 實作了Observerable接口,對Observerable接口的三個方法進行了具體實作
 *
 */
public class WechatServer implements Observerable {
    
    //注意到這個List集合的泛型參數為Observer接口,設計原則:面向接口程式設計而不是面向實作程式設計
    private List<Observer> list;
    private String message;
    
    public WechatServer() {
        list = new ArrayList<Observer>();
    }
    
    @Override
    public void registerObserver(Observer o) {
        
        list.add(o);
    }
    
    @Override
    public void removeObserver(Observer o) {
        if(!list.isEmpty())
            list.remove(o);
    }

    //周遊
    @Override
    public void notifyObserver() {
        for(int i = 0; i < list.size(); i++) {
            Observer oserver = list.get(i);
            oserver.update(message);
        }
    }
    
    public void setInfomation(String s) {
        this.message = s;
        System.out.println("微信服務更新消息: " + s);
        //消息更新,通知所有觀察者
        notifyObserver();
    }

}           

觀察者

  • 1.觀察者需要定義統一的接口用以處理事件通知。
/***
 * 抽象觀察者
 * 定義了一個update()方法,當被觀察者調用notifyObservers()方法時,觀察者的update()方法會被回調。
 *
 */
public interface Observer {
    public void update(String message);
}

/**
 * 觀察者
 * 實作了update方法
 *
 */
public class User implements Observer {

    private String name;
    private String message;
    
    public User(String name) {
        this.name = name;
    }
    
    @Override
    public void update(String message) {
        this.message = message;
        read();
    }
    
    public void read() {
        System.out.println(name + " 收到推送消息: " + message);
    }
    
}           

測試驗證

package com.jstao.observer;

public class Test {
    
    public static void main(String[] args) {
        WechatServer server = new WechatServer();
        
        Observer userZhang = new User("ZhangSan");
        Observer userLi = new User("LiSi");
        Observer userWang = new User("WangWu");
        
        server.registerObserver(userZhang);
        server.registerObserver(userLi);
        server.registerObserver(userWang);
        server.setInfomation("PHP是世界上最好用的語言!");
        
        System.out.println("----------------------------------------------");
        server.removeObserver(userZhang);
        server.setInfomation("JAVA是世界上最好用的語言!");
        
    }
}           

Tomcat實作的觀察者模式

  • 1.觀察者實作統一的接口LifecycleListener,實作具體的方法lifecycleEvent。
  • 2.觀察者的事件對象繼承了EventObject類,這個有興趣可以研究下。
  • 3.觀察者的具體實作以HostConfig為例,實作了具體的lifecycleEvent方法。
public final class LifecycleEvent extends EventObject {
    private static final long serialVersionUID = 1L;

    public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
        super(lifecycle);
        this.type = type;
        this.data = data;
    }

    private final Object data;
    private final String type;

    public Object getData() {
        return data;
    }

    public Lifecycle getLifecycle() {
        return (Lifecycle) getSource();
    }

    public String getType() {
        return this.type;
    }
}


public interface LifecycleListener {
    public void lifecycleEvent(LifecycleEvent event);
}



public class HostConfig implements LifecycleListener {

    public void lifecycleEvent(LifecycleEvent event) {

        try {
            host = (Host) event.getLifecycle();
            if (host instanceof StandardHost) {
                setCopyXML(((StandardHost) host).isCopyXML());
                setDeployXML(((StandardHost) host).isDeployXML());
                setUnpackWARs(((StandardHost) host).isUnpackWARs());
                setContextClass(((StandardHost) host).getContextClass());
            }
        } catch (ClassCastException e) {
            log.error(sm.getString("hostConfig.cce", event.getLifecycle()), e);
            return;
        }

        if (event.getType().equals(Lifecycle.PERIODIC_EVENT)) {
            check();
        } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
            beforeStart();
        } else if (event.getType().equals(Lifecycle.START_EVENT)) {
            start();
        } else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
            stop();
        }
    }
}           

  • 1.被觀察者實作接口Lifecycle,實作addLifecycleListener和removeLifecycleListener方法。
  • 2.容器的基類LifecycleBase實作了被觀察者功能,提供List lifecycleListeners儲存被觀察者。
  • 3.容器的具體實作當中都是繼承LifecycleBase類,是以天然包含了被觀察者的功能。
package org.apache.catalina;

public interface Lifecycle {
    public void addLifecycleListener(LifecycleListener listener);
    public LifecycleListener[] findLifecycleListeners();
    public void removeLifecycleListener(LifecycleListener listener);
}



public abstract class LifecycleBase implements Lifecycle {

    private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();
    private volatile LifecycleState state = LifecycleState.NEW;

    public void addLifecycleListener(LifecycleListener listener) {
        lifecycleListeners.add(listener);
    }

    public LifecycleListener[] findLifecycleListeners() {
        return lifecycleListeners.toArray(new LifecycleListener[0]);
    }

    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycleListeners.remove(listener);
    }

    protected void fireLifecycleEvent(String type, Object data) {
        LifecycleEvent event = new LifecycleEvent(this, type, data);
        for (LifecycleListener listener : lifecycleListeners) {
            listener.lifecycleEvent(event);
        }
    }
}           

參考文章

繼續閱讀