首页
学习
活动
专区
圈层
工具
发布

【设计模式-观察者模式】

【导读】队列中有一种模式是发布/订阅模式,订阅者可以有多个,当发布者发布了消息的时候,订阅者会收到通知,这就是观察者模式,也可以理解为生产者/消费者。

一、定义

定义了对象之间一对多的依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化后,它的所有观察者都会收到通知并更新。

二、实例

比如微信的朋友圈,当有好友发了朋友圈动态之后你会收到一个通知,就是朋友圈入口的那个红点。

此时朋友圈是一个被观察者,你的账号是一个观察者。

Java提供了Observable(被观察者)和Observer(观察者),只需继承这两个类就可以实现观察者模式。

朋友圈动态:表明是谁发了什么内容的朋友圈

代码语言:javascript
复制
public class Trends {

    private String userName;
    private String content;

    public Trends(String userName, String content) {
        this.userName = userName;
        this.content = content;
    }

}

朋友圈对象:

代码语言:javascript
复制
public class FriendCircle extends Observable {
    
    public void productTrends(Trends trends) {
        System.out.println(trends.getUserName()+"发了一条朋友圈,内容是:"+trends.getContent());
        1、这方法表明被观察者状态有更新
        setChanged();
        2、通知所有观察者
        notifyObservers(trends);
    }
}

微信账号:

代码语言:javascript
复制
public class WechatCount implements Observer{
    1、账号昵称
    private String userName;

    public WechatCount(String userName) {
        this.userName = userName;
    }

   2、收到通知后,会获取相应的内容进行逻辑处理
    @Override
    public void update(Observable o, Object arg) {
        Trends trends = (Trends) arg;
        System.out.println(this.userName+"接收到一条朋友圈动态更新通知,是"+trends.getUserName()+"发布的,内容是:"+trends.getContent());
        System.out.println(this.userName+"评论说:你真TM恶心");
    }
}

测试类:

代码语言:javascript
复制
public static void main(String[] args) {
      1、定义一个朋友圈(被观察者)
      FriendCircle friendCircle = new FriendCircle();
      2、定义账号(观察者)
      WechatCount wechatCount = new WechatCount("Liusy");
      3、注册观察者
      friendCircle.addObserver(wechatCount);
      4、更新状态
      friendCircle.productTrends(new Trends("张三","今天终于舔到女神了,我tm真优秀"));

  }

结果:

类图:

源码解析:

(1)为什么观察者可以收到通知?

因为被观察者包含了一个观察者的集合。

观察者需要进行注册:

当被观察者调用setChanged方法的时候,改变的是charged这个属性值

代码语言:javascript
复制
 protected synchronized void setChanged() {
        changed = true;
    }

然后会调用notifyObservers方法通知观察者

代码语言:javascript
复制
 public void notifyObservers(Object arg) {
      
        Object[] arrLocal;

        synchronized (this) {
            1、setCharged方法
            if (!changed)
                return;
            arrLocal = obs.toArray();
            2、将charged重置为false 
            clearChanged();
        }
        3、遍历观察者,调用其update方法
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

上述代码表明被观察者更新后为什么观察者会收到通知。

下一篇
举报
领券