首页 > 其他分享 >设计模式之观察者模式

设计模式之观察者模式

时间:2023-07-02 16:12:31浏览次数:38  
标签:Observer msgList void 观察者 模式 设计模式 public subject

定义

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式的UML类图及说明

 

 

如上图(图片来源于《head_first设计模式》)所示,观察者的uml中主要有以下类

1.主题Subject(接口)

Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法,主要为观察者注册方法(registerObserver),观察者删除方法(removeObserver),通知观察者方法(notifyObservers)

2.观察者Observer(接口)

Observer观察者一般是一个接口,每一个实现该接口的实现类都是具体观察者。主要提供一个update方法。

3.具体主题ConcreteSubject(Subject的具体实现)

是对主题Subject接口的具体实现,该类可根据具体业务扩展

4.具体观察者ConcreteObserver(Observer的具体实现)

是对Observer观察者的具体实现,一般订阅者会有多个,所以该类可通过自己需要的消息进行扩展

观察者模式的优缺点及应用场景

优点:

1.观察者和被观察者是抽象耦合的。

2.建立一套触发机制。

缺点:

1.如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

2.如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

3.观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

应用场景:

1.关联行为场景

2.事件多级触发场景

4.跨系统的消息变换场景,如消息队列的处理机制

应用实例:

1.新闻的发布订阅

2.天气信息的发布订阅

注意事项:

1、JAVA 中已经有了对观察者模式的支持类。

2、避免循环引用。

3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

Spring中的观察者模式

1.事件(ApplicationEvent)

ApplicationEvent 是所有事件对象的父类。ApplicationEvent 继承自 jdk 的 EventObject, 所有的事件都需要继承 ApplicationEvent, 并且通过source得到事件源。

2.事件监听(ApplicationListener)

ApplicationListener 事件监听器,也就是观察者。继承自 jdk 的 EventListener,该类中只有一个方法 onApplicationEvent。当监听的事件发生后该方法会被执行。

3.事件发布(ApplicationContext)

ApplicationContext 是 Spring 中的核心容器,在事件监听中 ApplicationContext 可以作为事件的发布者,也就是事件源。因为 ApplicationContext 继承自 ApplicationEventPublisher。在 ApplicationEventPublisher 中定义了事件发布的方法 — publishEvent(Object event)

4.事件管理(
ApplicationEventMulticaster)


ApplicationEventMulticaster 用于事件监听器的注册和事件的广播。监听器的注册就是通过它来实现的,它的作用是把 Applicationcontext 发布的 Event 广播给它的监听器列表。

观察者模式的实现

现在的线上直播模式非常的火,在这里,以简单的LOL比赛信息订阅为例。比如我们要关注今天有哪些了LPL的比赛信息,后几天有哪些比赛信息,我们就可以点击订阅,订阅后,有新的比赛信息,就会推送给你。

这样的场景下,我们就可以用观察者模式来实现:

定义主题接口

/**
 * 主题接口,对象通过此接口注册为观察者,或者把自己从观察者中删除
 *
 * @author yyl
 */
public interface Subject {

    /**
     * 观察者注册
     *
     */
    void registerObserver(Observer observer);

    /**
     * 删除观察者
     *
     */
    void removeObserver(Observer observer);

    /**
     * 通知观察者
     *
     */
    void notifyObservers();
}

  

定义主题接口的具体实现,及LOL比赛信息主题

/**
 * lol主题
 *
 * @author yyl
 */
public class LolSubject implements Subject {

    /** 今日比赛信息*/
    private String msg;

    /** 后几日比赛信息*/
    private List<String> msgList;

    // 用户列表
    private static List<Observer> userList = new ArrayList<>();

    @Override
    public void registerObserver(Observer observer) {
        userList.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        userList.remove(observer);
    }

    @Override
    public void notifyObservers() {
        userList.forEach(observer -> observer.update());
    }

    /**
     * 发布信息,并通知观察者
     *
     * @author yyl
     */
    public void setMsgs(String msg,List<String> msgList){
        // 更改通知信息
        this.msg = msg;
        this.msgList = msgList;
        // 通知观察者
        notifyObservers();
    }

    public String getMsg() {
        return msg;
    }

    public List<String> getMsgList() {
        return msgList;
    }
}

  

定义观察者Observer

/**
 * 观察者Observer,观察者一般是一个接口,每一个实现该接口的实现类都是具体观察者
 *
 * @author yyl
 */
public interface Observer {
    /**
     * 接受消息后的具体逻辑处理
     */
    void update();
}

  

具体观察者,今日比赛信息观察者

/**
 * 具体观察者,今日比赛信息观察者
 *
 * @author yyl
 */
public class CurrentObserver implements Observer {

    /**lol比赛信息主题 */
    private LolSubject subject;

    /**订阅的信息 */
    private String msg;

    public CurrentObserver(LolSubject subject) {
        this.subject = subject;
        // 观察者注册
        this.subject.registerObserver(this);
    }

    @Override
    public void update() {
        this.msg = this.subject.getMsg();
        System.out.println("今日比赛:" + this.msg);
    }
}

  

具体观察者,后几日比赛信息观察者

/**
 * 具体观察者,后几日比赛信息观察者
 *
 * @author yyl
 */
public class FutureObserver implements Observer {

    /**lol比赛信息主题 */
    private LolSubject subject;

    /**订阅的信息 */
    private List<String> msgList;

    public FutureObserver(LolSubject subject) {
        this.subject = subject;
        // 观察者注册
        this.subject.registerObserver(this);
    }

    @Override
    public void update() {
        this.msgList = this.subject.getMsgList();
        System.out.println("比赛预告:");
        msgList.forEach(s -> System.out.println(s));
    }
}

  

通知者进行通知 Client

public class TestObserver {

    public static void main(String[] args) {

        // 主题
        LolSubject lolSubject = new LolSubject();
        // 观察者
        CurrentObserver currentObserver = new CurrentObserver(lolSubject);
        FutureObserver futureObserver = new FutureObserver(lolSubject);

        List<String> msgList = new ArrayList<>();
        msgList.add("2020-06-22 RNG VS IG");
        msgList.add("2020-06-22 VG VS LGD");
        msgList.add("2020-06-22 V5 VS OMG");
        // 发布信息
        lolSubject.setMsgs("TSE VS FPX", msgList);
    }

}

  

如上代码,有两个观察者,在发布信息的比赛信息后,观察者就可以获取自己关注的信息,然后进行自己的业务逻辑处理。代码输出如下

 

标签:Observer,msgList,void,观察者,模式,设计模式,public,subject
From: https://www.cnblogs.com/fcjedorfjoeij/p/17520889.html

相关文章

  • SpringBoot 插件化开发模式
    1、Java常用插件实现方案1.2、serviceloader方式serviceloader是java提供的spi模式的实现。按照接口开发实现类,而后配置,java通过ServiceLoader来实现统一接口不同实现的依次调用。而java中最经典的serviceloader的使用就是Java的spi机制。1.2.1、javaspiSPI全称ServiceProv......
  • [PLC]Proface普洛菲斯进入离线模式的方法
       进入离线的方法参考手册第M.1.2章节进入离线模式    Proface ChinaTechnical Support DepartmentSky 进入离线的方法参考手册第M.1.2章节进入离线模式 进入离线的方法•  方法1  上电时直接进入离线在显示开始画面后, 触摸屏幕右......
  • Cocos Creator开发之MVC模式初探
    设计模式是用来实现软件设计进行分工的。设计模式应该是小巧的,对具体问题提出解决方案,以提高代码复用率,提高代码耦合性。CocosCreator中引入MVC模式的主要目的是:为了帮助CocosCreator开发者脱离拖拽脚本导致的后期维护方面带来的困难。一、基本的MVC模式组成控制器(Controller)-负......
  • 模式的真正价值是什么?
    在于交付的时候解决方案是否能正常工作并满足需求。模式就是其他人已经遇到过并加以分类的问题的解决方案。重构模式的时候需要判断是否能够更好地适应未来的变化,并对当前的解决方案有所改进。软件架构师大多是关于决定的。反模式是一种介绍如何从问题演化到不好的解决方案的模......
  • PostgreSQL 数据库与模式(二)
    删除数据库如果确定一个库不需要了,可以使用DROPDATABASE语句删除一个数据库(工作中谨慎删库):DROPDATABASE[IFEXISTS]name;如果使用了IFEXISTS,删除一个不存在的数据库时不会产生错误信息。删除数据库会同时删除该数据库中所有的对象,以及文件系统中的数据目录。只有数据库......
  • Settle Finance:以区块链技术为核心的P2P借贷模式
    "在数字化世界中,我们看到了许多技术进步如何推动金融行业的革新。其中,Peer-to-Peer(P2P)借贷模式的出现为借贷市场带来了新的可能性。然而,这个模式也带来了诸多问题,尤其是在信任和安全性方面。随着区块链技术的兴起,我们看到了它在改善P2P模式中的这些问题上的巨大潜力。区块链的......
  • ACM模式机考准备指南
    1熟练掌握格式化输入输出方法ACM模式需要题目要求,按照规定的格式自己手动写输入和输出的代码,如果没有充分准备,考试的时候就有可能会在输入输出这块卡很久,浪费考试的时间,反之,如果能够掌握各种格式的输入输出方法,则可以让我们在考试的时候快速完成输入输出代码的编写,节省出更多的......
  • 什么是 CSR、SSR、SSG、ISR - 渲染模式详解
    本文以React、Vue为例,介绍下主流的渲染模式以及在主流框架中如何实现上述的渲染模式。前置知识介绍看渲染模式之前我们先看下几个主流框架所提供的相关能力,了解的可跳到下个章节。挂载组件到DOM节点这是主流框架最基本的能力,就是将组件渲染到指定的DOM节点上。在React......
  • 10.8 多例模式
    本质上与单例模式没有区别classColor{ //在类内部提供有若干个实例化对象,如果为了方便管理,也可以通过对象数组的形式定义; privatestaticfinalColorRED=newColor("红色");//实例化对象 privatestaticfinalColorGREEN=newColor("绿色"); privatestaticfi......
  • Windows兼容模式怎么设置?140.210.18.x
    服务器兼容是什么意思?服务器兼容性怎么改?兼容性(compatibility)是指硬件之间、软件之间或是软硬件组合系统之间的相互协调工作的程度。兼容的概念比较广,相对于硬件来说,几种不同的电脑部件,如CPU、主板、显示卡等,如果在工作时能够相互配合、稳定地工作,就说它们之间的兼容性比较好,反之就......