头图

前言

🧐 王经理:上课了,上课了,今天讲一下什么是观察者模式,我们平时的代码实践中,很多都有观察者模式的思想运用,今天可是干货满满,好好听,不懂同学,你咋还在发呆

🙁 甄不懂:王经理,你可别提了,小美发了个朋友圈,说是想看电影,我刚点了个赞,准备去找她让她今晚和我一起去,结果手机瞬间50多个消息,一看全是给小美点赞的,我肯定没希望了

🙁 甄不懂:经理还是你正道的光,让小美留下来和我一起加班,别去看电影

🧐 王经理:你好好听今天的课,表现的好,我让小美和你一起看电影

🤪 不懂露出了开心的微笑:真的嘛,快快快,经理快开讲


正文

🧐 王经理:观察者模式就是定义了对象之间的一对多的依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者(观察者)都会收到通知并更新

😪 不懂:Zzzzz

😠 王经理:不懂,你还在睡觉,还想不想和小美看电影了

🤥 不懂吸了吸鼻子:当然想去了,经理你说的太抽象了,不好理解

😠 王经理:定义都是这么抽象的,一会带你 coding 一下就懂了,其实这个定义就很像,你给小美的朋友圈点赞了,你就监听了小美的这条朋友圈主题,一旦其他人给小美的这条朋友圈点赞,你作为观察者,也能收到相对应的信息

🙁 不懂:虽然我听懂了,但是很扎心

😎 王经理:好,接下来,我们以 摇号拿车牌的指标 作为例子,我们开始 coding

我们先定一个摇号结果的 dto LotteryResult 这个 dto 记录摇号的一些信息,比如摇号者是谁、什么时候进行的摇号、摇号结果是啥

我们让这个 dto 去继承 Observable 这个类,继承之后,这个类就是一个被观察者对象

public class LotteryResult extends Observable {
    /**
     * 用户名称
     */
    private String userName;
    /**
     * 摇号结果
     */
    private String msg;
    /**
     * 摇号时间
     */
    private Date dateTime;
}

然后在这个 dto 里去写一个 produceLotteryResult 方法,主要目的就是告诉监听者这个 dto 发生了变化,你自己看着办

    public void produceLotteryResult(LotteryResult result){
        // 标记已发生变化
        setChanged();
        // 通知监听者
        notifyObservers();
    }

被观察者准备好了,接下来就是监听者 SendLotteryResultListener 上场了

监听者需要去实现一个 Observer 方法,去接受观察者变化的信息

代码如下

public class SendLotteryResultListener implements Observer {

    /**
     * This method is called whenever the observed object is changed. An
     * application calls an <tt>Observable</tt> object's
     * <code>notifyObservers</code> method to have all the object's
     * observers notified of the change.
     *
     * @param o the observable object.
     * @param arg an argument passed to the <code>notifyObservers</code>
     */
    @Override
    public void update(Observable o, Object arg) {
        LotteryResult result =  (LotteryResult) o;
        System.out.println(result.getUserName() + "摇号结果为" + result.getMsg());
    }
}

万事具备,开始测试

public class Test {
    public static void main(String[] args) {

        SendLotteryResultListener listener = new SendLotteryResultListener();

        LotteryResult lotteryResult = new LotteryResult();
        // 添加监听者
        lotteryResult.addObserver(listener);
        lotteryResult.setUserName("张三");
        lotteryResult.setMsg("摇号成功");
        lotteryResult.setDateTime(new Date());

        lotteryResult.produceLotteryResult(lotteryResult);
    }
}
---------------- 输出结果
张三摇号结果为摇号成功

测试成功 👍🏻,我们的 监听者收到了被观察者变化的信息

🤨 不懂:妙啊,王经理,这个和之前杨小帅和我讲的那个 Spring Event 是不是有异曲同工之妙啊

🤓 王经理:不懂啊,你今天是开窍了,你说的非常对,那你可以写一个 demo 出来吗?

🤨 不懂:可以啊

----------------------------------------------------
@RestController
public class EventRequest implements ApplicationContextAware {
private ApplicationContext appContext;

@RequestMapping("/testEvent")
public String testEventSave(String name) {
    appContext.publishEvent(new LotteryResult(this, name));
    return "ok";
}

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    appContext = applicationContext;
}
}
--------------------------------------------------
// 监听者
@Component
public class WebEventListener {
/**
 * 仅监听字段值为 老王 时,类为 User.class 时
 */
@EventListener(classes = LotteryResult.class, condition = "#result.name == '老王'")
public void listen(LotteryResult result){
    // TODO
}

/**
 * 监听 LotteryResult.class 情况
 */
@EventListener(classes = LotteryResult.class)
public void listen1(LotteryResult result){
    // TODO
}
}

🤓 王经理:不错不错,那今天的课就到此结束

🥺 不懂:不是说,让我和小美看电影吗?

🤓 王经理收拾了一下电脑,走开了:你也不看看现在几点了,小美早就和别人看电影去了。

留下了不懂在一旁默默哭泣

20200205895554_JEglcB

总结

观察者模式作为一种行为模式,在结构上是满⾜开闭原则的,当你需要新增其他的监听事件或者修改监听逻辑,是不

需要改动事件处理类的。但是可能你不能控制调⽤顺序以及需要做⼀些事件结果的返回继续操作,所以使⽤的过程时需要考虑场景的合理性。


文章结束 🤣

如果本文对你有所帮助的话,那就点个赞吧

更多分享尽在微信公众号【codeLiveHouse】

公众号回复 “资料” 可以获取大厂面试题/技术文档/电子书等等


往期推荐

面试官竟然和我死磕 Maven

生产上数据库死锁,是该程序员祭天了


Issues
10 声望1 粉丝

热爱音乐,享受生活,希望分享可以帮助到有需要的人