设计模式——观察者模式
Posted studentytj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式——观察者模式相关的知识,希望对你有一定的参考价值。
观察者模式
定义
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。
类图
例子
假设由这样一个例子,大家都比较关注房价,所以关注了一个网站,利用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来实现的。
其他
- 观察者模式定义了对象之间一对多的关系
- 主题(也就是可观察者)用一个共同的接口来更新观察者。
- 使用观察者模式,可以采用推或者拉的模式
以上是关于设计模式——观察者模式的主要内容,如果未能解决你的问题,请参考以下文章