目录

[TOC]

什么是观察者模式

观察者模式也叫发布订阅模式

观察者模式(Observer Pattern)是一种设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,它的所有依赖者都会收到通知并自动更新

当多个人都关注了一个公众号时,这个公众号一发布新的文章,所有关注的账号都会收到消息

观察者模式的核心思想是将观察者对象注册到主题对象中,当主题对象的状态发生改变时,通知所有的观察者对象进行更新。这种设计模式可以帮助我们实现松耦合的对象间交互,从而提高系统的可维护性和可扩展性

观察者模式包含以下几个角色:

  1. 抽象主题(Subject):定义了一种抽象接口,用于添加、删除和通知观察者对象。
  2. 具体主题(ConcreteSubject):实现了抽象主题接口,维护了一组观察者对象,并在状态发生改变时通知它们。
  3. 抽象观察者(Observer):定义了一种抽象接口,用于接收主题对象的通知。
  4. 具体观察者(ConcreteObserver):实现了抽象观察者接口,存储主题对象的引用,并在收到通知时更新自己的状态。

UML类图

imgimg

代码

img

代码

被观察者,或者叫订阅主题

首先是上官无雪这个绿茶婊的类

先定义一个接口,很简单,包含一个用来订阅的方法add和取消订阅的方法remove。还有一个当状态发生改变时,用来通知其观察者的方法notifyState

1
2
3
4
5
6
7
public interface GreenTeaBitchSubject {
void add(TianDogObserver observer);

void remove(TianDogObserver observer);

void notifyState(String state);
}

接下来是其实现类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ShangGuanSubject implements GreenTeaBitchSubject{
private List<TianDogObserver> tianDogs = new ArrayList<>();

@Override
public void add(TianDogObserver observer) {
tianDogs.add(observer);
}

@Override
public void remove(TianDogObserver observer) {
tianDogs.remove(observer);
}

@Override
public void notifyState(String state) {
for (TianDogObserver tianDog : tianDogs) {
tianDog.update(state);
}
}
}

也非常简单,其持有一个对其感兴趣的观察者集合,当状态发生改变时就循环通知每个观察者。

观察者,或者叫订阅者

先定义一个观察者接口,里面只有一个方法,观察者就是在这个方法里面接收被观察者发送的状态改变通知。

1
2
3
public interface TianDogObserver {
void update(String message);
}

这里我们实现一个舔狗王二狗类

1
2
3
4
5
6
7
8
9
10
11
12
public class Dog2WangObserver implements TianDogObserver{
@Override
public void update(String message) {
if("肚子好饿".equals(message)){
System.out.println("二狗:半夜起来,翻墙出去步行2公里买女神最爱吃的小笼包... 上官:二狗,你真是个好人");
}else if("心情不好".equals(message)){
System.out.println("二狗:官哭着述说渣男怎么欺负的她...整整3个小时,全程安慰... 上官:二狗,你真是个好人");
}else {
System.out.println("随叫随到...");
}
}
}

可以看到,在update方法中,接收到女神的通知后,根据不同的状态做出了相应的动作。

西门淫荡类差不多,就省略了,可以从文章最后的源码查看…

客户端使用

客户端调用时,先给被观察者通过add添加观察者,也就是让二狗和西门订阅上官的状态,以便于上官状态改变时可以得到通知。最后使用notifyState来通知观察者状态改变了。如果某个观察者不再对被观察者感兴趣,直接使用remove方法取消订阅即可。最后王二狗被绿茶婊上官伤透了心,和牛翠华走到了一起,从此二狗就不再关心上官的状态了,直接使用remove方法取消订阅。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ObserverClient {
public void sendThink(){
GreenTeaBitchSubject subject = new ShangGuanSubject();
Dog2WangObserver dog2WangObserver = new Dog2WangObserver();
subject.add(dog2WangObserver);
subject.add(new YinDangObserver());

System.out.println("------午夜12点,肚子好饿,找个人来买东西吃------");
subject.notifyState("肚子好饿");
System.out.println("------又被渣男甩了,有点小难过,找个人来安慰一下------");
subject.notifyState("心情不好");
System.out.println("------二狗终于看透了上官这个绿茶婊,和牛翠花走到了一起------");
subject.remove(dog2WangObserver);
System.out.println("------上官又被渣男甩了,想找个人来安慰一下,却不见了那个好人的身影------");
subject.notifyState("心情不好");
}
}

输出:

1
2
3
4
5
6
7
8
9
------午夜12点,肚子好饿,找个人来买东西吃------
二狗:半夜起来,翻墙出去步行2公里买女神最爱吃的小笼包... 上官:二狗,你真是个好人
西门:是吗?那我下面给你吃啊?上官:讨厌拉...
------又被渣男甩了,有点小难过,找个人来安慰一下------
二狗:官哭着述说渣男怎么欺负的她...整整3个小时,全程安慰... 上官:二狗,你真是个好人
西门:南门那边新开了一家酒吧,晚上带你去放松一下吧... 上官:好嗨吆,感觉人生达到了高峰..
------二狗终于看透了上官这个绿茶婊,和牛翠花走到了一起------
------上官又被渣男甩了,想找个人来安慰一下,却不见了那个好人的身影------
西门:南门那边新开了一家酒吧,晚上带你去放松一下吧... 上官:好嗨吆,感觉人生达到了高峰..

总结

观察者模式的应用非常广泛,例如在各种消息中间件中,如kafka、rabitmq等,例如RxJava 等等。其实Java从1.0就对观察者模式进行了支持,提供了两个类型java.util.Observablejava.util.Observer 但其在Java9时候被标记为废弃状态,所以我们这里也就不提了,感兴趣的小伙伴可以去看看

当前由于各种框架和第三方开源库的使用,程序设计的要求被降的很低,大部分人终日都在写胶水代码和业务代码,什么设计模式,压根不知道,不知道也照样写代码…。这个是IT产业化不可逆转的趋势,不然为什么IT从业人员被划归为新型民工的行列了呢?就是因为我们正在变成工地上按照设计图纸一块一块垒砖的农民工的样子。不过我们也不应该妄自菲薄,搬砖是为了生活,不断探寻是为了梦想…