事件驱动模型-观察者模式实现

事件驱动模型-观察者模式实现案例

在上一篇中我们讨论了事件驱动模型的实现方式,其中用观察者模式实现的方式又有同步驱动、异步驱动两种,本片将给出这两种实现的案例。

同步驱动事件

1 定义接口

public interface Event {

}

 

public interface EventListener {
    void notifyEvent(Event e);
}

 

public interface EventSource {
    void addListener(EventListener e);
    void removeListener(EventListener e);
}

 

2 定义数据元

public class WeatherData {
    private int temperature = 0;
    private int humidity = 0;
    private int pressure = 0;
    
    public WeatherData() {
       
    }
    
    public WeatherData(int temperary, int humidity, int pressure) {
        this.temperature = temperary;
        this.humidity = humidity;
        this.pressure = pressure;
    }
    
    public boolean equals(int temperature, int humidity, int pressure) {
        return (this.temperature == temperature) && (this.humidity == humidity) && (this.pressure == pressure);
    }
    
    public int getTemperature() {
        return temperature;
    }
    
    public int getHumiDity() {
        return humidity;
    }

    public int getPressure() {
        return pressure;
    }
    
    public int getTemperatureVar(int temperature) {
        return temperature - this.temperature;
    }
    
    public int getHumidityVar(int humidity) {
        return humidity - this.humidity;
    }

    public int getPressureVar(int pressure) {
        return pressure - this.pressure;
    }
    
    public void update(int temperary, int humidity, int pressure) {
        this.temperature = temperary;
        this.humidity = humidity;
        this.pressure = pressure;
    }
}

 

3 实现Event

public class WeatherDataChangeEvent implements Event{
    private final int temperatureVar;
    private final int humidityVar;
    private final int pressureVar;
    
    public WeatherDataChangeEvent(int tempVar, int humVar, int pressVar) {
        this.temperatureVar = tempVar;
        this.humidityVar = humVar;
        this.pressureVar = pressVar;
    }
    
    public int getTemperatureVar() {
        return temperatureVar;
    }
    
    public int getHuminityVar() {
        return humidityVar;
    }
    
    public int getPressureVar() {
        return pressureVar;
    }
    
}

 

4 实现EventListener

public class TemperatureListener implements EventListener {
    private int temperatrue = 0; 
    @Override
    public void notifyEvent(Event e) {
        int temperatrueVar = ((WeatherDataChangeEvent)e).getTemperatureVar();
        temperatrue += temperatrueVar;
        System.out.printf("  |- temperatrue[diff=%d] = %d\n", temperatrueVar, temperatrue);
    }

}

 

public class HumidityListener implements EventListener {
    private int humidity = 0;
    @Override
    public void notifyEvent(Event e) {
        int humidityVar = ((WeatherDataChangeEvent)e).getHuminityVar();
        humidity += humidityVar;
        System.out.printf("  |- humidity[diff=%d] = %d\n", humidityVar, humidity);
    }
}

 

public class PressureListener implements EventListener {
    private int pressure = 0;
    @Override
    public void notifyEvent(Event e) {
        int pressureVar = ((WeatherDataChangeEvent)e).getPressureVar();
        pressure += pressureVar;
        System.out.printf("  |- pressure[diff=%d] = %d\n", pressureVar, pressure);
    }

}

 

5 实现EventSource

public class WeatherStation implements EventSource {

    List<EventListener> listeners = new LinkedList<EventListener>();
    WeatherData data = new WeatherData();
    
    @Override
    public void addListener(EventListener listener) {
        listeners.add(listener);
    }

    @Override
    public void removeListener(EventListener e) {
        listeners.remove(e);
    }

    public void monitor() {
        System.out.println("\n*************** Weather Station is Working... *******************");
        System.out.println("Enter \"exit\" to Exit");
        System.out.println("Enter \"[temperature] [humidity] [pressure]\" to Fill Weather Datas");
        System.out.println("*******************************************************************\n");
        monitor(new Scanner(System.in));
    }
    
    private void monitor(Scanner sc) {
        while(true) {
            if(sc.hasNext("exit"))
            {
                System.out.println("Weather Station exited!!!");
                System.exit(0);
            }
            updateMeasurement(sc.nextInt(), sc.nextInt(), sc.nextInt());
            sc.nextLine();
        }
    }
    
    private void updateMeasurement(int temperature, int humidity, int pressure) {
        if(!data.equals(temperature, humidity, pressure)) {
            Event e = getEvent(data.getTemperatureVar(temperature), data.getHumidityVar(humidity), data.getPressureVar(pressure)); 
            data.update(temperature, humidity, pressure);
            dispatch(e);
        }
    }
    
    private Event getEvent(int temperatureVar, int humidityVar, int pressureVar) {
        return new WeatherDataChangeEvent(temperatureVar, humidityVar, pressureVar);
    }

    private void dispatch(Event e) {
        for(EventListener listener : listeners) {
            listener.notifyEvent(e);
        }
    }
}

 

异步驱动事件

异步驱动的代码与同步驱动的代码只有EventSource类的实现有区别,其余部分与同步驱动的代码一致。

1 定义接口

参考同步驱动代码。

2 定义数据元

参考同步驱动代码。

3 实现Event

参考同步驱动代码。

4 实现EventListener

参考同步驱动代码。

5 实现EventSource

public class WeatherStation implements EventSource{
    List<EventListener> listeners = new LinkedList<EventListener>();
    List<Event> events =new LinkedList<Event>(); 
    WeatherData data = new WeatherData();
    
    @Override
    public void addListener(EventListener listener) {
        listeners.add(listener);
    }

    @Override
    public void removeListener(EventListener listener) {
        listeners.remove(listener);
    }
    
    public void monitor() {
        System.out.println("\n*************** Weather Station is Working... *******************");
        System.out.println("Enter \"exit\" to Exit");
        System.out.println("Enter \"[temperature] [humidity] [pressure]\" to Fill Weather Datas");
        System.out.println("*******************************************************************\n");
        Scanner sc = new Scanner(System.in);
        new Thread(new Runnable() {
            @Override
            public void run() {
                monitor(sc);
            }}).start();;
        new Thread(new Runnable() {
            @Override
            public void run() {
                dispatch();
            }}).start();;
    }
    
    private void monitor(Scanner sc) {
        while(true) {
            if(sc.hasNext("exit"))
            {
                System.out.println("Weather Station exited!!!");
                System.exit(0);
            }
            updateMeasurement(sc.nextInt(), sc.nextInt(), sc.nextInt());
            sc.nextLine();
        }
    }
    
    private void updateMeasurement(int temperature, int humidity, int pressure) {
        if(!data.equals(temperature, humidity, pressure)) {
            Event e = getEvent(data.getTemperatureVar(temperature), data.getHumidityVar(humidity), data.getPressureVar(pressure)); 
            data.update(temperature, humidity, pressure);
            stashEvent(e);
        }
    }
    
    private Event getEvent(int temperatureVar, int humidityVar, int pressureVar) {
        return new WeatherDataChangeEvent(temperatureVar, humidityVar, pressureVar);
    }

    private void stashEvent(Event e) {
        synchronized(events) {
            System.out.println("[+++] Stash Event To Event List...");
            events.add(e);
            events.notify();
        }
    }

    private void dispatch() {
        Event event;
        while(true) {
            synchronized(events) {
                while(events.isEmpty()) {
                    try {
                        events.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("\n[---] Remove Event From Event List...");
                event = events.iterator().next();
                events.remove(event);
            }
            dispatch(event);
        }
    }
    
    private void dispatch(Event e) {
        for(EventListener listener : listeners) {
            listener.notifyEvent(e);
        }
    }

}

这里采用多线程实现了异步驱动,因为单线程下的异步驱动看不出明显的异步效果。与同步驱动的EventSource相比,异步驱动的EventSource增加了List<Event> events用于缓存Even。在方法updateMeasurement(int temperature, int humidity, int pressure)中生成Event后不再直接调用方法dispatch(Event e)通知EventListener,而是先调用方法stashEvent(Event e)将Event添加到List<Event> events中,然后另一个线程通过方法ispatch()挑选Even并通知EventListener

测试类

public class SyncWeatherEventTest {

    public static void main(String[] args) {
        
        WeatherStation station = new WeatherStation();
        station.addListener(new PressureListener());
        station.addListener(new HumidityListener());
        station.addListener(new TemperatureListener());
        station.monitor();
        
    }

}

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值