zoukankan      html  css  js  c++  java
  • 设计模式——观察者模式

    观察者模式

    定义

    观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。

    类图

    例子

    假设由这样一个例子,大家都比较关注房价,所以关注了一个网站,利用rss订阅。当有新的动态更新时,所有订阅的用户就会收到最新的消息。

    定义主题及其实现House Site

    package com.gitlearning.hanldegit.patterns.observe.first;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 房子站点
     */
    public class HouseSite implements Subject{
    
        private List<Subscriber> observers;
    
        public HouseSite() {
            observers = new ArrayList<>();
        }
    
        @Override
        public void registerObserver(Subscriber subscriber) {
            observers.add(subscriber);
        }
    
        @Override
        public void removeObserver(Subscriber subscriber) {
            observers.remove(subscriber);
        }
    
        @Override
        public void publishMessage(String message) {
            observers.forEach(observer -> observer.updateMessage(message));
        }
    
    }
    
    interface Subject {
        void registerObserver(Subscriber subscriber);
        void removeObserver(Subscriber subscriber);
        void publishMessage(String message);
    }
    
    

    定义订阅者及其实现:

    package com.gitlearning.hanldegit.patterns.observe.first;
    
    public interface Subscriber {
    
        void updateMessage(String message);
    }
    
    class Person implements Subscriber{
        String name;
    
        public Person(String name) {
            this.name = name;
        }
    
        @Override
        public void updateMessage(String message) {
            System.err.println(name + "收到了最新消息: " + message);
        }
    }
    
    
    

    测试程序如下:

    package com.gitlearning.hanldegit.patterns.observe.first;
    
    import org.junit.jupiter.api.Test;
    
    public class TestObserver {
        @Test
        void test() {
            Subject houseSite = new HouseSite();
            Person zhangsan = new Person("张三");
            Person lisi = new Person("李四");
            houseSite.registerObserver(zhangsan);
            houseSite.registerObserver(lisi);
            houseSite.publishMessage("今日涨价房源100套,降价房源888套。");
    
            houseSite.removeObserver(lisi);
            houseSite.publishMessage("今日有事,网站暂停更新");
        }
    }
    
    

    输出消息为:

    张三收到了最新消息: 今日涨价房源100套,降价房源888套。
    李四收到了最新消息: 今日涨价房源100套,降价房源888套。
    张三收到了最新消息: 今日有事,网站暂停更新
    

    其实JAVA本身就提供了对观察者模式的支持,主题类Observable

    package com.gitlearning.hanldegit.patterns.observe.userInternal;
    
    import java.util.Observable;
    
    public class HouseSite extends Observable {
        void publishEvent(String message) {
            setChanged();
            notifyObservers(message);
        }
    }
    
    

    观察者Observer:

    package com.gitlearning.hanldegit.patterns.observe.userInternal;
    
    import java.util.Observable;
    import java.util.Observer;
    
    public class Person implements Observer {
        String name;
    
        public Person(String name) {
            this.name = name;
        }
    
        @Override
        public void update(Observable o, Object arg) {
            System.err.println(name + "收到了最新消息: " + arg);
        }
    }
    
    

    测试代码:

    package com.gitlearning.hanldegit.patterns.observe.userInternal;
    
    import org.junit.jupiter.api.Test;
    
    import java.util.Observer;
    
    public class TestObserverWithInternal {
        @Test
        void test() {
            HouseSite site = new HouseSite();
            Observer zhangsan = new Person("张三");
            Observer lisi = new Person("李四");
            site.addObserver(zhangsan);
            site.addObserver(lisi);
            site.publishEvent("今日最新消息, 首套房利率上浮25%");
    
            site.deleteObserver(zhangsan);
            site.publishEvent("离岸人民币汇率破7!");
        }
    }
    
    

    结果:

    李四收到了最新消息: 今日最新消息, 首套房利率上浮25%
    张三收到了最新消息: 今日最新消息, 首套房利率上浮25%
    李四收到了最新消息: 离岸人民币汇率破7!
    

    这里需要注意一点,需要在Observable里设置changed状态,要不然无法调用update方法。

    使用

    Spring的ApplicationEvent继承自jdk中的EventObject,ApplicationListener继承自EventListener。

    发布事件的时候触发监听器的onApplicationEvent方法,那触发的方法就在于ApplicationContext中。例如AbstractApplication的refresh()方法里的registerListeners(),通过ApplicationEventMulticaster广播出去,触发监听器的onApplicationEvent方法。

    顺便讲一下,ApplicationEventPublisher有publishEvent方法,其实也是通过调用MultiCaster来实现的。

    其他

    1. 观察者模式定义了对象之间一对多的关系
    2. 主题(也就是可观察者)用一个共同的接口来更新观察者。
    3. 使用观察者模式,可以采用推或者拉的模式
    当你准备好了,机会来临的时候,你才能抓住
  • 相关阅读:
    BZOJ 3555: [Ctsc2014]企鹅QQ hash
    bzoj 4300: 绝世好题 dp
    Codeforces Round #192 (Div. 1) C. Graph Reconstruction 随机化
    Codeforces Round #192 (Div. 1) B. Biridian Forest 暴力bfs
    Codeforces Round #192 (Div. 1) A. Purification 贪心
    HDU 5514 Frogs 容斥定理
    HDU 5515 Game of Flying Circus 二分
    HDU 5521 Meeting 最短路
    HDU 5510 Bazinga 暴力匹配加剪枝
    HDU 5512 Meeting 博弈论
  • 原文地址:https://www.cnblogs.com/studentytj/p/11329814.html
Copyright © 2011-2022 走看看