【设计模式】观察者模式(定义 | 特点 | Demo入门讲解)

news/2024/10/7 1:51:22 标签: 设计模式, 观察者模式, windows

文章目录

    • 定义
    • 结构
    • Demo | 代码
      • Subject目标类
      • Observer抽象观察者
      • 观察者1 | CPU监听器
      • 观察者2 | 内存监听器
      • 客户端 | Client
    • 优点
      • 适合场景

定义

所谓观察者模式就是你是被观察的那个对象,你爸爸妈妈就是观察者,一天24h盯着你,一旦你不听话,他们要你听话,你的状态发生变化以后,他们接收到你的状态发生了改变。

image-20240704145502974

结构

如下图,服务器就作为被观察者,三个传感器就是观察者。这是一种抽象的表达方式!

image-20240704145601787

image-20240704150528837

  • Subject被观察的目标
  • Observer观察者抽象类
  • 具体观察者实现类
  • Client客户端

Demo | 代码

Subject目标类

我们需要一个Subject目标类,内部含有观察者对象的集合,在必要的时候触发事件。

  • Subject被观察的目标
  • Observer观察者抽象类
  • 具体观察者实现类
  • Client客户端

/**
 * 这个Server类就是服务类,作为Subject,别观察的目标!
 * @author linghu
 * @date 2024/7/4 11:50
 */
public class Server {

    private List<Observer> observers= new ArrayList<Observer>();
    private int cpu;
    private int memory;

    public Server() {

    }

    //变更服务器状态
    public void changeState(int cpu,int memory){
        this.cpu=cpu;
        this.memory=memory;
        System.out.println("CPU:" + cpu + "%,内存占用:" + memory + "%");
        //通知所有观察者对象,使它们能够自动更新自己
        notifyAllObservers();
    }

    public Server(int cpu, int memory) {
        this.cpu = cpu;
        this.memory = memory;
    }

    public int getCpu() {
        return cpu;
    }

    public void setCpu(int cpu) {
        this.cpu = cpu;
    }

    public int getMemory() {
        return memory;
    }

    public void setMemory(int memory) {
        this.memory = memory;
    }
    public void addObserver(Observer observer){
        observers.add(observer);
    }
    public void notifyAllObservers(){
        for (Observer observer :observers) {
            observer.update();
        }
    }

}

Observer抽象观察者

这个抽象主要是封装了目标对象和观察者要做的事情。

/**
 * @author linghu
 * @date 2024/7/4 12:02
 */
public abstract class Observer {
    protected Server subject;//服务类,目标对象
    public abstract void update();//观察者要做的事情
}

观察者1 | CPU监听器

/**
 * @author linghu
 * @date 2024/7/4 12:04
 * CPU监听器
 */
public class CpuObserver extends Observer{

    //传入目标类subject
    public CpuObserver(Server subject) {
        //初始化的时候完成数据双向绑定工作
        this.subject=subject;
        this.subject.addObserver(this);
    }

    @Override
    public void update() {
        //监听CPU的运行状况,负载超过80%就发出警报
        if(subject.getCpu() >= 80){
            System.out.println("警报:CPU当前" + subject.getCpu()+ "%即将满载,请 速查明原因");
        }
    }
}

观察者2 | 内存监听器

/**
 * @author linghu
 * @date 2024/7/4 12:46
 * 内存监听器
 */
public class MemoryObserver extends Observer{

    public MemoryObserver(Server subject) {
        this.subject=subject;
        this.subject.addObserver(this);
    }

    @Override
    public void update() {
        if(subject.getMemory() >= 80){
            System.out.println("警报:服务器内存已经占用超过" + subject.getMemory()+ "%即将满载,请 速查明原因");
        }
    }
}

客户端 | Client

/**
 * 观察者模式:让多个观察者对象同时监听某一个主题对象。
 * 这个主题对象在状态发生变化时,会通知所有观察者对象,
 * 使它们能够自动更新自己。
 * @author linghu
 * @date 2024/7/4 12:49
 * 客户端
 */
public class Client {
    public static void main(String[] args) throws InterruptedException {
        Server subject = new Server();
        //完成两个观察者和一个目标类的绑定
        //引入新的观察者,这里可以利用反射,动态加载~
        new CpuObserver(subject);
        new MemoryObserver(subject);
        //==============================
        while (true){
            int cpu=new Random().nextInt(100);
            int memory=new Random().nextInt(100);
            //调用具体的业务~
            subject.changeState(cpu,memory);
            Thread.sleep(5000);//5s
        }
    }
}

优点

  • 开闭原则。 你⽆需修改发布者代码就能引⼊新的订阅者类 (如果是发布者接⼝则可轻松引⼊发布者类)。

  • 你可以在运⾏时建⽴对象之间的联系。

适合场景

  • 所有的发布订阅模式
  • 构建事件监听机制,比如按下触发click事件

http://www.niftyadmin.cn/n/5545270.html

相关文章

飞睿智能无线高速uwb安全数据传输模块,低功耗、抗干扰超宽带uwb芯片传输速度技术新突破

在信息化的时代&#xff0c;数据传输的速度和安全性无疑是每个企业和个人都极为关注的话题。随着科技的飞速发展&#xff0c;超宽带&#xff08;Ultra-Wideband&#xff0c;简称UWB&#xff09;技术凭借其性能和广泛的应用前景&#xff0c;逐渐成为了数据传输领域的新星。今天&…

挑战杯 opencv python 深度学习垃圾图像分类系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; opencv python 深度学习垃圾分类系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 这是一个较为新颖的竞…

用Conda配置 Stable Diffusion WebUI 1.9.4

用Conda配置 Stable Diffusion WebUI 1.9.4 本文主要讲解: 如何用Conda搭建Stable Diffusion WebUI 1.9.4环境&#xff0c;用Conda的方式安装&#xff0c;不需要单独去安装Cuda了。 1. 安装miniconda https://docs.anaconda.com/free/miniconda/index.html 2. 搭建虚拟环境…

文本到图像的革新:自动化Prompt优化的UF-FGTG框架

在文本到图像合成领域&#xff0c;已经能够由文本描述直接生成图像。然而&#xff0c;尽管这一技术带来了无限的可能性&#xff0c;它仍然面临着一个关键挑战&#xff1a;如何设计出能够引导模型生成高质量图像的提示&#xff08;prompts&#xff09;。尤其是对于初学者而言&am…

LLM之RAG实战(四十一)| 使用LLamaIndex和Gemini构建高级搜索引擎

Retriever 是 RAG&#xff08;Retrieval Augmented Generation&#xff09;管道中最重要的部分。在本文中&#xff0c;我们将使用 LlamaIndex 实现一个结合关键字和向量搜索检索器的自定义检索器&#xff0c;并且使用 Gemini大模型来进行多个文档聊天。 通过本文&#xff0c;我…

2024.7.8

2024.7.8 【追逐影子的人&#xff0c;自己就是影子 —— 荷马】 Monday 六月初三 讲的根本听不懂好吧&#xff01; 目前只写了三道题&#xff08;但是黑色 确实是没见过这么抽象的数据结构 Gregor and the Two Painters Number of Components Equal LCM Subsets 这个lcm确实…

self_attention python代码

self_attention面试code from math import sqrt import torch import torch.nn as nnclass SA(nn.Module):def __init__(self, dimQ, dimK, dimV):super(SA, self).__init__()self.dimQ dimQself.dimK dimKself.dimV dimV# self.mid 10self.linerQ nn.Linear(self.dimQ, s…

构造函数语意学(The Semantics of Constructors)

1、“Default Constructor” 的构造操作 下面4种情况编译器会生成默认构造函数&#xff1a; 成员类对象带有默认构造函数父类带有默认构造函数带有虚表的类带有虚基类的类 1.1、 成员类对象带有默认构造函数 如果一个类没有任何构造函数&#xff0c;但它的一个成员对象带有…