新闻八卦我在行(观察者模式) - 第357篇_收集

我女朋友喜欢八卦,于是我每天就收集逗她玩。

(1)今年北京大学校花出炉,神似某个明星

(2)老板当众指责员工“长得丑”

(3)和AI结婚,需要对其忠诚吗

       我女朋友在我的八卦里,每天都是笑容满面。

新闻八卦我在行(观察者模式) - 第357篇_收集_02

后来,我弟弟,我姐姐知道我每天会收集八卦信息,就说:反正一个人看是看,两个人看也是,你顺便也发一份给我们。

       为了管理谁需要,谁不需要,我就说你们有需要的就订阅我把,有订阅我的,我就发送给他。

       这就是观察者模式,和发布订阅有点相似。

一、观察者模式(Observer)基本概念

观察者模式就如一个聊天室,当你需要收到聊天室的消息时,你就注册成为聊天室的成员,当聊天室有信息更新时,就会传到你那去。当你不需要接收聊天室的信息时,可以注销掉,退出聊天室。

又例如,天气观测站和气象报告板的关系。但报告板想获取观测站的数据,可以注册加入到观测站的观察者列表中,这就可以使观测站有数据更新时,自动传给气象报告板。

 

1.1 定义

观察者模式(Observer Pattern)定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

 

1.2 类图

新闻八卦我在行(观察者模式) - 第357篇_收集_03

1.3 主要角色

(1)抽象观察者角色(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

(2)具体观察者角色(ConcreteObserver):实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。

(3)抽象被观察者角色(Subject):也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。

(4)具体被观察者角色(ConcreteSubject):也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。

 

 

二、观察者模式之订阅八卦

       这么多人都觉得我的八卦有趣,那么我就得管理这些人,设计模式之《观察者模式》就满足了我的需求。

2.1 类图

新闻八卦我在行(观察者模式) - 第357篇_收集_04

2.2 编码

2.2.1 抽象观察者角色(Observer)

抽象观察者角色(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

新闻观察者NewsObserver:

  •  
package com.kfit.observer.news;
/** * 新闻观察者 * * 抽象观察者角色(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。 * * @author 悟纤「公众号SpringBoot」 * @date 2020-12-03 * @slogan 大道至简 悟在天成 */public interface NewsObserver { void update(String msg);}

 

2.2.2 具体观察者角色(ConcreteObserver)

具体观察者角色(ConcreteObserver):实现抽象观察者角色所需要的更新接口,一边使本身的状态与制图的状态相协调。

具体观察者角色GirlFriend:

  •  
package com.kfit.observer.news;
/** * 具体观察者角色 * * @author 悟纤「公众号SpringBoot」 * @date 2020-12-03 * @slogan 大道至简 悟在天成 */public class GirlFriend implements NewsObserver { @Override public void update(String msg) { System.out.println("女朋友接收到信息:"+msg); }}

抽象被观察者角色(Subject):也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。

新闻主题抽象NewsSubject:

  •  
package com.kfit.observer.news;
import java.util.Observer;
/** * 新闻主题抽象 * * @author 悟纤「公众号SpringBoot」 * @date 2020-12-03 * @slogan 大道至简 悟在天成 */public interface NewsSubject { void addObserver(NewsObserver newsObserver); void removeObserver(NewsObserver newsObserver); void notify(String msg);}

 

2.2.3 具体被观察者角色(ConcreteSubject)

具体被观察者角色(ConcreteSubject):也就是一个具体的主题,在集体主题的内部状态改变时,所有登记过的观察者发出通知。

       我就是收集消息,然后将信息通知到各个观察者:

  •  
package com.kfit.observer.news;
import java.util.ArrayList;import java.util.List;
/** * 具体被观察者角色(ConcreteSubject):也就是一个具体的主题, * 在集体主题的内部状态改变时,所有登记过的观察者发出通知。 * * @author 悟纤「公众号SpringBoot」 * @date 2020-12-03 * @slogan 大道至简 悟在天成 */public class Me implements NewsSubject { private List<NewsObserver> newsObservers = new ArrayList<>();
@Override public void addObserver(NewsObserver newsObserver) { newsObservers.add(newsObserver); }
@Override public void removeObserver(NewsObserver newsObserver) { newsObservers.remove(newsObserver); }


@Override public void notify(String msg) { for(NewsObserver newsObserver:newsObservers){ newsObserver.update(msg); } }}

2.3 测试

       到这里可以测试一下了:

  •  
package com.kfit.observer.news;
/** * 测试观察者模式 * * @author 悟纤「公众号SpringBoot」 * @date 2020-12-03 * @slogan 大道至简 悟在天成 */public class Client { public static void main(String[] args) { //我准备一下 NewsSubject me = new Me();
//女朋友、妹妹 NewsObserver girlFriend = new GirlFriend(); NewsObserver sister = new Sister();
//添加到观察者列表中 me.addObserver(girlFriend); me.addObserver(sister);
//我找呀找... 找到了一条八卦... me.notify("今年北京大学校花出炉,神似某个明星");
//妹妹说,最近事情很多,没时间看了,就不要发给我了 me.removeObserver(sister);
//我找呀找,找到了一条 System.out.println(); me.notify("老奶奶过马路到底要不要扶"); }}

       执行结果:

新闻八卦我在行(观察者模式) - 第357篇_收集_05

 

   越分享越成长,越分享越自信

  通过本文,你最大的是收获是什么?请在留言区分享你的收获。

 

我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。