码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式——观察者模式

时间:2019-08-09 23:35:09      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:技术   not   状态   each   输出   动态   sub   nal   object   

观察者模式

定义

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

类图

技术图片

例子

假设由这样一个例子,大家都比较关注房价,所以关注了一个网站,利用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. 使用观察者模式,可以采用推或者拉的模式

设计模式——观察者模式

标签:技术   not   状态   each   输出   动态   sub   nal   object   

原文地址:https://www.cnblogs.com/studentytj/p/11329814.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!