其他分享
首页 > 其他分享> > 设计模式之观察者模式(Observer Pattern)

设计模式之观察者模式(Observer Pattern)

作者:互联网

观察者模式(Observer Pattern)

1.场景引入

很久很久之前,我们获知世界大事都是要通过报纸的。而报社的业务就是出版报纸,向某家报社订阅报纸,只要他们有新报纸出版,就会给你送过来。当你不想再看报纸时,取消订阅,他们就不会再送新报纸过来了。

再比如,你在B站上关注了一个UP主,只要他一更新视频,你就会收到他的更新通知。不想再看时,则可以取关。

上面两种场景中体现的便是典型的观察者模式,这些场景主要分为两种角色,一种是发行报纸/更新视频的角色, 另一种则是订阅报纸/订阅更新的角色。前一种角色我们称之为主题(Subject),而后一种角色我们称之为观察者(Observer)。

2.定义

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

解释一下:在现实世界中,许多对象并不是独立存在。一个主题对象状态发生变化时,许多依赖于该对象的其他观察者对象都需要发生变化。我们在类中可以模拟实现这种一对多依赖关系。具体做法是,当主题对象(Subject)内部的变量发生变化,它就去主动通知依赖于自己的所有观察者对象(Observer)。观察者模式可以将观察者和被观察的对象分离开,实现了两者之间的松耦合。

观察者模式的结构图

3.组成部分

1. 抽象主题(Subject):

把所有观察者对象的引用保存到一个集合里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

2. 具体主题(ConcreteSubject):

将有关状态变量存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出更新通知。

3. 抽象观察者(Observer):

为所有的具体观察者定义一个接口,在得到主题通知时更新自己。

4. 具体观察者(ConcreteObserver):

实现抽象观察者所定义的更新接口,以便主题对象在状态更新时通知观察者对象。

4.具体实现

实现观察者模式有很多形式,比较常用的是使用“注册—通知—撤销注册”的方法。

具体做法是:主题对象维护一个内部状态字段和一个观察者列表,当主题对象的状态发生变化时,依次通知列表中的观察者。同时,观察者维护一个主题对象的引用,主要是实现从主题对象中进行主题以及撤销注册的操作。

好的!经过上面的许多介绍,相信大家都已经对观察者模式有所了解了,那么现在我们就开始实战一下!

具体场景是做一个B站UP主更新视频时,将更新信息推送到所有关注该UP主的用户上。

备注:我个人喜欢在接口名前加大写I(表示Interface),个人习惯,不喜勿喷!

第一步:定义抽象主题接口(ISubject接口)

/***
 * 抽象主题接口
 */
public interface ISubject {
    // 注册观察者
    void registerObserver(IObserver observer);
    // 移除观察者
    void removeObserver(IObserver observer);
    // 通知观察者
    void notifyObservers();
    // 更新内部状态
    void updateVideo(String videoName);
}

第二步:定义具体的主题类(UpLoader类)

import java.util.ArrayList;
import java.util.List;

public class UpLoader implements ISubject {

    private List<IObserver> observers; // 维护一个观察者列表,用来实现通知操作
    private String videoName; // 维护一个内部状态,当更新视频时,videoName会发生变化

    /**
     * 构造器,用来初始化observers和videoName
     */
    public UpLoader() {
        this.observers = new ArrayList<>();
        this.videoName = null;
    }

    /**
     * uploader更新视频
     * @param videoName
     */
    public void updateVideo(String videoName) {
        this.videoName = videoName;
        notifyObservers(); // 通知所有的用户(观察者)
    }

    /**
     * 用户(观察者)注册到该UpLoader上
     * @param observer
     */
    @Override
    public void registerObserver(IObserver observer) {
        observers.add(observer); // 添加到观察者列表上
    }

    /**
     * 移除观察者
     * @param observer
     */
    @Override
    public void removeObserver(IObserver observer) {
        observers.remove(observer);
    }

    /**
     * 通知所有的观察者
     */
    @Override
    public void notifyObservers() {
        for (IObserver observer : observers) {
            observer.update(videoName); // 通知用户(观察者)视频更新了
        }
    }
}

第三步:定义抽象观察者接口(IObserver接口)

public interface IObserver {
    // 用来通知观察者主题状态发生更新
    void update(String videoName);
    // 取消关注主题对象
    void removeUpLoader();
}

第四步:定义具体的用户观察者类(UserObserver类)

public class UserObserver implements IObserver {
    private ISubject uploader; // 绑定的UP主
    private String username; // 用户名

    /**
     * 构造器
     * @param uploader
     * @param username
     */
    public UserObserver(ISubject uploader, String username) {
        this.uploader = uploader;
        this.username = username;
        uploader.registerObserver(this); // 关注Up主
    }

    /**
     * 通知该用户视频更新了
     * @param videoName
     */
    @Override
    public void update(String videoName) {
        System.out.println("奥力给!" + username +  ",您关注的UP主更新视频了,视频名为:" + videoName + ",快去一键三连吧~~~");
    }

    /**
     * 把Up主取消关注
     */
    public void removeUpLoader() {
        this.uploader.removeObserver(this);
    }
}

第五步:功能测试(ObserverTest类)

public class ObserverTest {
    public static void main(String[] args) {
        // 构造一个UP主(主题)
        ISubject uploader = new UpLoader();
        // 建立三个用户(观察者)
        IObserver user1 = new UserObserver(uploader, "小明");
        IObserver user2 = new UserObserver(uploader, "小浩");
        IObserver user3 = new UserObserver(uploader, "小志");

        // up主第一次更新视频
        uploader.updateVideo("小猪佩奇");

        System.out.println("--------------------------------------------------------------------");

        // user2小浩取消关注up主
        user2.removeUpLoader();
        // up主第二次更新视频
        uploader.updateVideo("喜洋洋与灰太狼");

    }
}

测试结果:

观察者模式测试结果

5.分析

结尾词

好了,观察者模式的介绍就到此为止了,它的设计方式也比较简单,相信大家肯定已经完全了解了它的使用方法。

最后,希望本文能给大家带来帮助,谢谢!

参考文章:https://www.runoob.com/design-pattern/observer-pattern.html

https://zhuanlan.zhihu.com/p/51357583

http://c.biancheng.net/view/1390.html

标签:videoName,Observer,对象,Pattern,主题,观察者,uploader,设计模式,public
来源: https://www.cnblogs.com/yimeixiaobai1314/p/14695849.html