设计模式之观察者模式

简介: 设计模式之观察者模式

观察者模式

所有源代码地址 https://gitee.com/zyxscuec/Design-pattern.git

文章目录

(1) 概念

观察者模式(Observer Pattern)定义了对象之间的一对多依赖,让多个观察者对象同时监听一个主体对象,当主体对象发生变化时,它的所有依赖者(观察者)都会收到通知并更新,属于行为型模式。观察者模式有时也叫做发布订阅模式。

(2)适用场景

观察者模式主要用于在关联行为之间建立一套触发机制的场景。观察者模式在现实生活应用也非常广泛,

比如:微信朋友圈动态通知、GPser 生态圈消息通知、邮件通知、广播通知、桌面程序的事件响应等(如下图)。

如果有设置指定老师回答,对应的老师就会收到邮件通知,这就是观察者模式的一种应用场

景。我们可能会想到 MQ,异步队列等,其实 JDK 本身就提供这样的 API

(3) 代码示例

我们用代码来还原一下这样一个应用场景,创建 GPer 类:

package com.alibaba.design.observerpattern.gperadvice;
import java.util.Observable;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/30-9:42
 */
public class GPer extends Observable {
    private String name = "GPer生态圈";
    private static GPer gper = null;
    private GPer(){}
    public static GPer getInstance(){
        if(null == gper){
            gper = new GPer();
        }
        return gper;
    }
    public String getName() {
        return name;
    }
    public void publishQuestion(Question question){
        System.out.println(question.getUserName() + "在" + this.name + "上提交了一个问题。");
        setChanged();
        notifyObservers(question);
    }
}

创建问题 Question 类:

package com.alibaba.design.observerpattern.gperadvice;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/30-9:43
 */
public class Question {
    private String userName;
    private String content;
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }
}

创建老师 Teacher 类:

package com.alibaba.design.observerpattern.gperadvice;
import java.util.Observable;
import java.util.Observer;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/30-9:43
 */
public class Teacher implements Observer {
    private String name;
    public Teacher(String name){
        this.name = name;
    }
    @Override
    public void update(Observable o, Object arg) {
        GPer gper = (GPer)o;
        Question question = (Question)arg;
        System.out.println("===============================");
        System.out.println(name + "老师,你好!\n" +
                "您收到了一个来自“" + gper.getName() + "”的提问,希望您解答,问题内容如下:\n" +
                question.getContent() + "\n" +
                "提问者:" + question.getUserName());
    }
}

客户端测试代码

package com.alibaba.design.observerpattern.gperadvice;
import java.util.Observer;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/30-9:44
 */
public class ObserverTest {
    public static void main(String[] args) {
        GPer gper = GPer.getInstance();
        Teacher tom = new Teacher("Tom");
        Teacher mic = new Teacher("Jerry");
        //这为没有@Tom老师
        Question question = new Question();
        question.setUserName("小明");
        question.setContent("观察者设计模式适用于哪些场景?");
        gper.addObserver(tom);
        gper.addObserver(mic);
        gper.publishQuestion(question);
    }
}

(4) 模式在源码中的体现

来看一下 Spring 中的 ContextLoaderListener 实现了 ServletContextListener 接口,ServletContextListener 接口又继承了 EventListener,在 JDK 中 EventListener 有非常广泛的应用。我们可以看一下源代码,ContextLoaderListener:

package org.springframework.web.context;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
    public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
    public ContextLoaderListener() {
    }
    public ContextLoaderListener(WebApplicationContext context) {
      super(context);
    }
    @override     
    public void contextInitialized(ServletContextEvent event) {
      this.initWebApplicationContext(event.getServletContext());
    }
    @override    
    public void contextDestroyed(ServletContextEvent event) {
      this.closeWebApplicationContext(event.getServletContext());
      ContextCleanupListener.cleanupAttributes(event.getServletContext());
    }
}

ServletContextListener

package javax.servlet;
import java.util.EventListener;
public interface ServletContextListener extends EventListener {
    public void contextInitialized(ServletContextEvent sce);
    public void contextDestroyed(ServletContextEvent sce);
}

EventListener

package java.util;
public interface EventListener {
}

(5)基于 Guava API 轻松落地观察者模式

Guava是一种基于开源的Java库,Google Guava源于2007年的"Google Collections Library"。这个库是为了方便编码,并减少编码错误。这个库用于提供集合,缓存,支持原语句,并发性,常见注解,字符串处理,I/O和验证的实用方法。

在这里,我还推荐给大家一个实现观察者模式非常好用的框架。API 使用也非常简单,举

个例子,先引入jar包:guava-20.jar

这里建议去maven下载这个

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>

创建侦听事件 GuavaEvent:

package com.alibaba.design.observerpattern.guava;
import com.google.common.eventbus.Subscribe;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/30-9:59
 */
public class GuavaEvent {
    @Subscribe
    public void subscribe(String str){
        System.out.println("执行subscribe方法,传入的参数是:" + str);
    }
}

客户端测试代码:

package com.alibaba.design.observerpattern.guava;
import com.google.common.eventbus.EventBus;
/**
 * @author zhouyanxiang
 * @create 2020-07-2020/7/30-9:59
 */
public class GuavaEventTest {
    public static void main(String[] args) {
        //消息总线
        EventBus eventBus = new EventBus();
        GuavaEvent guavaEvent = new GuavaEvent();
        eventBus.register(guavaEvent);
        eventBus.post("Tom");
    }
}

(6) 观察者模式的优缺点

  • 优点:
    1、观察者和被观察者之间建立了一个抽象的耦合。
    2、观察者模式支持广播通信。
  • 缺点:
    1、观察者之间有过多的细节依赖、提高时间消耗及程序的复杂度。
    2、使用要得当,要避免循环调用。


相关文章
|
13天前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
|
1月前
|
设计模式 传感器
【设计模式】观察者模式(定义 | 特点 | Demo入门讲解)
【设计模式】观察者模式(定义 | 特点 | Demo入门讲解)
37 0
|
9天前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
20 3
|
20天前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
33 9
|
19天前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
27 2
|
28天前
|
设计模式 监控 UED
设计模式之观察者模式
【10月更文挑战第12天】 观察者模式是一种行为型设计模式,定义了一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都会自动更新。主要由主题(被观察者)和观察者组成,实现对象间的松耦合,广泛应用于用户界面、事件驱动系统和数据监控等领域。
|
30天前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
本教程详细讲解Kotlin语法,适合深入学习。对于快速掌握Kotlin,推荐“简洁”系列教程。本文特别介绍了观察者模式,包括使用Java API和Kotlin委托属性(如Delegates.observable)实现的方法,旨在帮助开发者更高效地实现和优化观察者模式的应用。
32 3
|
2月前
|
设计模式 Java 关系型数据库
设计模式——观察者模式
观察者模式介绍、观察者模式优化天气预报案例、JDK 的Observable类和Observer类
设计模式——观察者模式
|
1月前
|
设计模式 监控 Java
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
Kotlin教程笔记(52) - 改良设计模式 - 观察者模式
28 0
|
3月前
|
设计模式 存储 前端开发
【十四】设计模式~~~行为型模式~~~观察者模式(Java)
文章详细介绍了观察者模式(Observer Pattern),这是一种对象行为型模式,用于建立对象之间的一对多依赖关系。当一个对象状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。文中通过交通信号灯与汽车的案例以及多人联机对战游戏的设计方案,阐述了观察者模式的动机和应用场景。接着,文章介绍了观察者模式的结构、角色、优点、缺点以及适用情况,并通过代码示例展示了如何在Java中实现观察者模式。此外,还探讨了观察者模式在MVC架构中的应用以及Java中对观察者模式的支持。
【十四】设计模式~~~行为型模式~~~观察者模式(Java)

热门文章

最新文章

  • 1
    C++一分钟之-设计模式:工厂模式与抽象工厂
    42
  • 2
    《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
    46
  • 3
    C++一分钟之-C++中的设计模式:单例模式
    53
  • 4
    《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
    37
  • 5
    《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
    61
  • 6
    Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
    56
  • 7
    Java面试题:设计模式在并发编程中的创新应用,Java内存管理与多线程工具类的综合应用,Java并发工具包与并发框架的创新应用
    40
  • 8
    Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
    49
  • 9
    Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
    105
  • 10
    Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
    75