【对象行为模式】二十三天玩转设计模式之观察者模式

你好,我是小黄,一名独角兽企业的Java开发工程师。
感谢茫茫人海中我们能够相遇,
俗话说:当你的才华和能力,不足以支撑你的梦想的时候,请静下心来学习,
希望优秀的你可以和我一起学习,一起努力,实现属于自己的梦想。

一、什么是观察者模式?

观察者一般可以看做是第三者,比如在学校上自习的时候,大家肯定都有过交头接耳、各种玩耍的经历,这时总会有一个“放风”的小伙伴,当老师即将出现时及时“通知”大家老师来了。再比如,拍卖会的时候,大家相互叫价,拍卖师会观察最高标价,然后通知给其它竞价者竞价,这就是一个观察者模式。
 
对于观察者模式而言,有两个对象,一个是观察者,一个是被观察者。
 
观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。UML结构图如下:

在这里插入图片描述

其中,各属性的定义:

  • Subject:被观察者
  • Observer:抽象观察者接口
  • ConcreteObserver:具体观察者,实现接口

二、为什么要用观察者模式?

大家在生活中可能都遇到这种问题:当孩子哭的时候,爸爸、妈妈应该第一时间收到消息,并且做出响应的对策。
在这里插入图片描述
如果我们不采取观察者模式,我们写出的代码可能是这种的:

在这里插入图片描述
这种代码在DadMum等观察者少量的时候还比较好用,当观察者的数量多起来,我们的类就会变得十分臃肿。

还有一个比较大的问题,对于观察者来说,不一定监控一个被观察者,可能同时监控多个被观察者,这样的话,我们上述简单的架构就会变得累赘。

原始的观察者模式在传递消息的时候,是通过观察者类和被观察者类之间的耦合通知,我们将消息的通知改为事件发送,也就是观察者和被观察者通过事件来进行通信。

三、如何实现观察者模式?

我们还是用上面小孩哭的例子,来进行一个架构图的绘制:

在这里插入图片描述
整体的思路:当我们的小孩哭了之后,会发送一个哭泣的消息事件,而我们的 observer 会监听这个事件并做出响应

Child:被观察者对象,发送哭泣的事件

class Child {
    private Boolean cry = false;
    private List<Observer> observers = new ArrayList<>();

    {
        observers.add(new Dad());
        observers.add(new Mum());
        observers.add(new Dog());
    }

    public boolean isCry() {
        return cry;
    }

    public void wakeUp() {
        cry = true;
        // 创建消息事件
        WakeUpEvent event = new WakeUpEvent(System.currentTimeMillis(), "bed", this);
        // 发送消息事件
        for (Observer observer : observers) {
            observer.actionOnWakeUp(event);
        }
    }
}

WakeUpEvent:事件发送事件、地点、事件源对象

class WakeUpEvent {
    long timestamp;
    String loc;
    // 事件源对象本身
    Child source;

    public WakeUpEvent(long timestamp, String loc, Child source) {
        this.timestamp = timestamp;
        this.loc = loc;
        this.source = source;
    }
}

Observer:观察者的接口

interface Observer {
    void actionOnWakeUp(WakeUpEvent event);
}

Dad:实现观察者接口,监听事件

class Dad implements Observer {
    public void feed() {
        System.out.println("dad feed");
    }

    @Override
    public void actionOnWakeUp(WakeUpEvent event) {
        feed();
    }
}

Test:测试

    public static void main(String[] args) {
        Child child = new Child();
        child.wakeUp();
        // dad feed
        // Mum bao
        // Dog wangwangwang
    }

四、总结

当我们想要一个对象状态改变,其他对象状态也跟着改变时,如果我们使用原始类耦合的做***造成我们的类显着特别的臃肿和难以维护。

这个时候,我们利用 观察者模式+事件机制,可以让我们整个系统的耦合度大大降低,并且在后续维护的过程中,也便于维护。

但是观察者也有一定的弊端,比如:

  • 我们的观察者并不知道被观察者做出了怎么样的改变,仅仅知道被观察者进行了变化
  • 一定避免循环观察,防止观察者和被观察者之间相互引用

本期的内容就到这里,我是一名独角兽企业的Java开发工程师,有问题可以留言或者私信加我微信,我们下期再见!

在这里插入图片描述

#Java##学习路径#
全部评论

相关推荐

和蔼:在竞争中脱颖而出,厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了
点赞 评论 收藏
分享
10-07 23:57
已编辑
电子科技大学 Java
八街九陌:博士?客户端?开发?啊?
点赞 评论 收藏
分享
1 1 评论
分享
牛客网
牛客企业服务