瑞_23种设计模式_观察者模式

文章目录

    • 1 观察者模式(Observer Pattern)
      • 1.1 介绍
      • 1.2 概述
      • 1.3 观察者模式的结构
      • 1.4 观察者模式的优缺点
      • 1.5 观察者模式的使用场景
    • 2 案例一
      • 2.1 需求
      • 2.2 代码实现
    • 3 案例二
      • 3.1 需求
      • 3.2 代码实现
    • 4 JDK中提供的观察者模式实现 ★
      • 4.1 Observable类
      • 4.2 Observer 接口
      • 4.3 案例

🙊 前言:本文章为瑞_系列专栏之《23种设计模式》的观察者模式篇。本文中的部分图和概念等资料,来源于博主学习设计模式的相关网站《菜鸟教程 | 设计模式》和《黑马程序员Java设计模式详解》,特此注明。本文中涉及到的软件设计模式的概念、背景、优点、分类、以及UML图的基本知识和设计模式的6大法则等知识,建议阅读 《瑞_23种设计模式_概述》

本系列 - 设计模式 - 链接:《瑞_23种设计模式_概述》

⬇️本系列 - 创建型模式 - 链接🔗

  单例模式:《瑞_23种设计模式_单例模式》
  工厂模式:《瑞_23种设计模式_工厂模式》
  原型模式:《瑞_23种设计模式_原型模式》
抽象工厂模式:《瑞_23种设计模式_抽象工厂模式》
 建造者模式:《瑞_23种设计模式_建造者模式》

⬇️本系列 - 结构型模式 - 链接🔗

  代理模式:《瑞_23种设计模式_代理模式》
 适配器模式:《瑞_23种设计模式_适配器模式》
 装饰者模式:《瑞_23种设计模式_装饰者模式》
  桥接模式:《瑞_23种设计模式_桥接模式》
  外观模式:《瑞_23种设计模式_外观模式》
  组合模式:《瑞_23种设计模式_组合模式》
  享元模式:《瑞_23种设计模式_享元模式》

⬇️本系列 - 行为型模式 - 链接🔗

模板方法模式:《瑞_23种设计模式_模板方法模式》
  策略模式:《瑞_23种设计模式_策略模式》
  命令模式:《瑞_23种设计模式_命令模式》
 职责链模式:《瑞_23种设计模式_职责链模式》
  状态模式:《瑞_23种设计模式_状态模式》
 观察者模式:《后续更新》
 中介者模式:《后续更新》
 迭代器模式:《后续更新》
 访问者模式:《后续更新》
 备忘录模式:《后续更新》
 解释器模式:《后续更新》

在这里插入图片描述

1 观察者模式(Observer Pattern)

瑞:观察者模式是一种常用的设计模式,常作用于分布式系统事件通知、业务对象交互、数据同步与缓存更新、实时数据监控等。

  观察者模式是一种行为型模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新

  当对象间存在一对多关系时,则使用观察者模式。比如,当一个对象被修改时,则会自动通知依赖它的对象。

  瑞:行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。
  瑞:行为型模式分为类行为模式对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性

观察者模式属于:对象行为模式

1.1 介绍

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

  • 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

  • 何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

  • 如何解决:使用面向对象技术,可以将这种依赖关系弱化。

  • 关键代码:在抽象类里有一个 ArrayList 存放观察者们。

  • 应用实例
      1️⃣ 拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。
      2️⃣ 西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。

  • 优点
      1️⃣ 观察者和被观察者是抽象耦合的。
      2️⃣建立一套触发机制。

  • 缺点
      1️⃣ 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
      2️⃣ 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
      3️⃣ 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

  • 使用场景
      1️⃣ 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
      2️⃣ 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
      3️⃣ 一个对象必须通知其他对象,而并不知道这些对象是谁。
      4️⃣ 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

  • 注意事项
      1️⃣ JAVA 中已经有了对观察者模式的支持类(但自JDK 9开始,java.util.Observable 和 java.util.Observer 由于使用频率不高且存在设计问题,已被标记为废弃
      2️⃣ 避免循环引用
      3️⃣ 如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式

1.2 概述

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

  观察者模式(发布订阅模式)有时也被称为模型-视图模式、源-收听者模式或从属者模式。它主要定义了对象间的一种一对多的依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都能得到通知并被自动更新。

  观察者模式通常用于实现分布式事件处理系统、新闻代理、状态监测等。这种模式可以使得一个对象的改变能够自动传递给所有依赖于它的观察者,从而实现对象之间的松耦合。例如,它可以用于构建消息发布/订阅系统,其中消息发布者作为被观察者,而订阅者则作为观察者。当发布者发布新消息时,所有订阅者都会收到通知并执行相应操作。此外,在图形用户界面(GUI)开发中,观察者模式常被用于处理用户界面组件之间的交互。当一个组件的状态发生变化时,其他依赖该组件的组件将自动更新以反映新的状态。在金融领域,观察者模式也可用于实现股票市场监控系统,使投资者能实时收到股票价格变动的通知。

1.3 观察者模式的结构

  • 观察者模式主要包含以下角色:
      1️⃣ Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
      2️⃣ ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
      3️⃣ Observer:抽象观察者,是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
      4️⃣ ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

1.4 观察者模式的优缺点

优点

  • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
  • 被观察者发送通知,所有注册的观察者都会收到信息【可以实现广播机制】

缺点

  • 如果观察者非常多的话,那么所有的观察者收到被观察者发送的通知会耗时。
  • 如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,会导致系统崩溃

1.5 观察者模式的使用场景

  • 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
  • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时。



2 案例一

【案例】微信公众号

2.1 需求

  在使用微信公众号时,大家都会有这样的体验,当你关注的公众号中有新内容更新的话,它就会推送给关注公众号的微信用户端。我们使用观察者模式来模拟这样的场景,微信用户就是观察者,微信公众号是被观察者,有多个的微信用户关注了程序猿这个公众号。

  类图如下:

在这里插入图片描述

2.2 代码实现


  定义抽象观察者类,里面定义一个更新的方法

抽象观察者类(接口)
/**
 * 抽象观察者类
 *
 * @author LiaoYuXing-Ray
 **/
public interface Observer {

    void update(String message);
}

  定义具体观察者类,微信用户是观察者,里面实现了更新的方法

微信用户(类)
/**
 * 具体的观察者角色类
 *
 * @author LiaoYuXing-Ray
 **/
public class WeiXinUser implements Observer {

    private final String name;

    public WeiXinUser(String name) {
        this.name = name;
    }

    public void update(String message) {
        System.out.println(name + "-" + message);
    }
}

  定义抽象主题类,提供了attach、detach、notify三个方法

抽象主题角色类(接口)
/**
 * 抽象主题角色类
 *
 * @author LiaoYuXing-Ray
 **/
public interface Subject {

    // 添加订阅者(添加观察者对象)
    void attach(Observer observer);

    // 删除订阅者
    void detach(Observer observer);

    // 通知订阅者更新消息
    void notify(String message);
}

  微信公众号是具体主题(具体被观察者),里面存储了订阅该公众号的微信用户,并实现了抽象主题中的方法

具体主题角色类(类)
import java.util.ArrayList;
import java.util.List;

/**
 * 具体主题角色类
 *
 * @author LiaoYuXing-Ray
 **/
public class SubscriptionSubject implements Subject {

    // 定义一个集合,用来存储多个观察者对象
    private final List<Observer> weiXinUserList = new ArrayList<Observer>();

    public void attach(Observer observer) {
        weiXinUserList.add(observer);
    }

    public void detach(Observer observer) {
        weiXinUserList.remove(observer);
    }

    public void notify(String message) {
        // 遍历集合
        for (Observer observer : weiXinUserList) {
            // 调用观察者对象中的update方法
            observer.update(message);
        }
    }
}

  客户端程序测试类

测试类
/**
 * 测试类
 *
 * @author LiaoYuXing-Ray
 **/
public class Client {
    public static void main(String[] args) {
        // 1.创建公众号对象
        SubscriptionSubject subject = new SubscriptionSubject();

        // 2.订阅公众号
        subject.attach(new WeiXinUser("Ray"));
        subject.attach(new WeiXinUser("瑞瑞"));
        subject.attach(new WeiXinUser("CSDN-Ray486"));

        // 3.公众号更新,发出消息给订阅者(观察者对象)
        subject.notify("《瑞_23种设计模式》专栏更新了!");
    }
}

  代码运行结果如下:

	Ray-《瑞_23种设计模式》专栏更新了!
	瑞瑞-《瑞_23种设计模式》专栏更新了!
	CSDN-Ray486-《瑞_23种设计模式》专栏更新了!

3 案例二

本案例为菜鸟教程中的案例

3.1 需求

  观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。

  ObserverPatternDemo,我们的演示类使用 Subject 和实体类对象来演示观察者模式。

在这里插入图片描述

3.2 代码实现

步骤 1

  创建 Subject 类。

Subject.java
import java.util.ArrayList;
import java.util.List;
 
public class Subject {
   
   private List<Observer> observers 
      = new ArrayList<Observer>();
   private int state;
 
   public int getState() {
      return state;
   }
 
   public void setState(int state) {
      this.state = state;
      notifyAllObservers();
   }
 
   public void attach(Observer observer){
      observers.add(observer);      
   }
 
   public void notifyAllObservers(){
      for (Observer observer : observers) {
         observer.update();
      }
   }  
}

步骤 2

  创建 Observer 类。

Observer.java
public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}

步骤 3

  创建实体观察者类。

BinaryObserver.java
public class BinaryObserver extends Observer{
 
   public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
      System.out.println( "Binary String: " 
      + Integer.toBinaryString( subject.getState() ) ); 
   }
}
OctalObserver.java
public class OctalObserver extends Observer{
 
   public OctalObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
     System.out.println( "Octal String: " 
     + Integer.toOctalString( subject.getState() ) ); 
   }
}
HexaObserver.java
public class HexaObserver extends Observer{
 
   public HexaObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
      System.out.println( "Hex String: " 
      + Integer.toHexString( subject.getState() ).toUpperCase() ); 
   }
}

步骤 4

  使用 Subject 和实体观察者对象。

ObserverPatternDemo.java
public class ObserverPatternDemo {
   public static void main(String[] args) {
      Subject subject = new Subject();
 
      new HexaObserver(subject);
      new OctalObserver(subject);
      new BinaryObserver(subject);
 
      System.out.println("First state change: 15");   
      subject.setState(15);
      System.out.println("Second state change: 10");  
      subject.setState(10);
   }
}

步骤 5

  执行程序,输出结果:

	First state change: 15
	Hex String: F
	Octal String: 17
	Binary String: 1111
	Second state change: 10
	Hex String: A
	Octal String: 12
	Binary String: 1010



4 JDK中提供的观察者模式实现 ★

  在 Java 中,通过 java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例。

瑞:需要注意的是:自JDK 9开始,java.util.Observable 和 java.util.Observer 由于使用频率不高且存在设计问题,已被标记为废弃。

4.1 Observable类

  Observable 类是抽象目标类(被观察者),它有一个 Vector 集合成员变量,用于保存所有要通知的观察者对象,下面来介绍它最重要的 3 个方法。

  • void addObserver(Observer o) 方法:用于将新的观察者对象添加到集合中。
  • void notifyObservers(Object arg) 方法:调用集合中的所有观察者对象的 update方法,通知它们数据发生改变。通常越晚加入集合的观察者越先得到通知。
  • void setChange() 方法:用来设置一个 boolean 类型的内部标志,注明目标对象发生了变化。当它为true时,notifyObservers() 才会通知观察者。

4.2 Observer 接口

  Observer 接口是抽象观察者,它监视目标对象的变化,当目标对象发生变化时,观察者得到通知,并调用 update 方法,进行相应的工作。

4.3 案例

【例】警察抓小偷

  警察抓小偷也可以使用观察者模式来实现,警察是观察者,小偷是被观察者。

  代码如下:

  1️⃣ 小偷是一个被观察者,所以需要继承Observable类

小偷 - 被观察者(类)
import java.util.Observable;

/**
 * 小偷 - 被观察者
 *
 * @author LiaoYuXing-Ray
 **/
public class Thief extends Observable {

    private String name;

    public Thief(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void steal() {
        System.out.println("小偷:我偷东西了,有没有人来抓我!!!");
        super.setChanged(); //changed  = true
        super.notifyObservers();
    }
}

  2️⃣ 警察是一个观察者,所以需要让其实现Observer接口

警察 - 观察者(类)

import java.util.Observable;
import java.util.Observer;

/**
 * 警察 - 观察者
 *
 * @author LiaoYuXing-Ray
 **/
public class Policemen implements Observer {

    private String name;

    public Policemen(String name) {
        this.name = name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("警察:" + ((Thief) o).getName() + ",我已经盯你很久了,你可以保持沉默,但你所说的将成为呈堂证供!!!");
    }
}
测试类
/**
 * 测试类
 *
 * @author LiaoYuXing-Ray
 **/
public class Client {
    public static void main(String[] args) {
        // 创建小偷对象
        Thief t = new Thief("隔壁老王");
        // 创建警察对象
        Policemen p = new Policemen("小李");
        // 让警察盯着小偷
        t.addObserver(p);
        // 小偷偷东西
        t.steal();
    }
}

  执行程序,输出结果:

	小偷:我偷东西了,有没有人来抓我!!!
	警察:隔壁老王,我已经盯你很久了,你可以保持沉默,但你所说的将成为呈堂证供!!!



本文是博主的粗浅理解,可能存在一些错误或不完善之处,如有遗漏或错误欢迎各位补充,谢谢

  如果觉得这篇文章对您有所帮助的话,请动动小手点波关注💗,你的点赞👍收藏⭐️转发🔗评论📝都是对博主最好的支持~


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/493712.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

修复ubuntu引导

一、制作ubuntu启动U盘 进入启动盘后&#xff0c;点击Try ubuntu&#xff0c;进入U盘的ubuntu系统。 二、配置和添加源 sudo add-apt-repository ppa:yannubuntu/boot-repair && sudo apt-get update三、运行 Boot Repair重新制作引导 sudo boot-repair注意&#x…

使用OpenXlab下载数据集(推荐)

OpenXLab浦源面向人工智能领域开发者和使用者,提供一站式AI开发平台。提供包括应用开发,模型免费托管,数据集下载等服务 官方网址:https://openxlab.org.cn/datasets?lang=zh-CN 提供了6622种数据集, 涉及计算机视觉、自然语言处理、多模态、通用机器学习、音频识别以及其他…

Bash and a Tough Math Puzzle 线段树维护区间gcd

还是一道很不错的题目&#xff0c;很容易想到用一棵线段树来维护区间gcd 注意用倍数来剪枝就好了&#xff0c;很是一到很好的题目的 #include<iostream> #include<vector> using namespace std; const int N 5e510; int n,q; struct Segment{int l,r;int d; }tr[…

Kubeflow文档1:介绍与架构

Kubeflow 2024/3/19版本的文档 此专栏用来展示相关的内容翻译&#xff0c;重点关注本地部署&#xff0c;关于运营商的方案&#xff0c;请自行查阅 文档地址https://www.kubeflow.org/docs/ 开始编辑时间&#xff1a;2024/3/27&#xff1b;最后编辑时间2024/3/27 Kubeflow文…

记录echarts各种地图json文件下载地址

今日绘图需要用到echarts的地图json文件&#xff0c;但是github上已经找不到了&#xff0c;后发现伟大的网友提供了地址如下&#xff1a;Index of /examples/data/asset/geohttps://echarts.apache.org/examples/data/asset/geo/ 免费下载实时更新的geoJson数据、行政区划边界…

【正点原子FreeRTOS学习笔记】————(4)FreeRTOS中断管理

这里写目录标题 一、什么是中断&#xff1f;&#xff08;了解&#xff09;二、中断优先级分组设置&#xff08;熟悉&#xff09;三、中断相关寄存器&#xff08;熟悉&#xff09;四、FreeRTOS中断管理实验&#xff08;掌握&#xff09; 一、什么是中断&#xff1f;&#xff08;…

leetCode刷题 20. 有效的括号

目录 题目&#xff1a; 1. 思路 2. 解题方法 3. 复杂度 4. Code 题目&#xff1a; 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型…

docker部署音乐播放下载器

可播放及下载音乐的工具 musicn 下载镜像 docker pull ghcr.m.daocloud.io/wy580477/musicn-container:latest创建数据目录 mkdir -p /data/musicdocker-compose部署 vim docker-compose.yml version: 3 services:musicn:container_name: musicnimage: ghcr.io/wy580477/m…

短信系统后台搭建要注意什么|网页版短信平台开发

在搭建短信系统后台时&#xff0c;需要注意以下几个关键方面&#xff0c;以确保系统的稳定性、安全性和高效性&#xff1a; 选择合适的技术栈&#xff1a;根据项目需求和团队实际情况选择合适的后端开发语言和框架&#xff0c;如Java Spring、Node.js、Python Django等。 系统…

深入理解React的setState机制

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

耳目一新的滑块版登录注册界面~

又到了毕业季&#xff0c;大家做毕设的时候总会参考已有的案例&#xff0c;不过大多产品的样式非常单一雷同。本帖博主给大家分享一个比较别树一帜的登录界面&#xff0c;如下&#xff1a; 如果没有账号&#xff0c;点击“去注册”&#xff0c;则会产生如下的效果&#xff1a; …

【Linux 08】进程概念

文章目录 &#x1f308; 01. 基本概念&#x1f308; 02. 描述进程 PCB&#x1f308; 03. 使用 ./ 的方式创建进程&#x1f308; 04. ps 查看进程&#x1f308; 05. getpid / getppid 获取进程标识符&#x1f308; 06. kill 终止指定进程&#x1f308; 07. fork 创建子进程&…

设置asp.net core WebApi函数输入和返回类型中的属性名称开头大小写格式

以下列类型定义为例创建简单的ASP.NET Core的WebApi函数&#xff0c;此时输入参数和返回结果的属性名称开头默认为小写&#xff0c;如下图所示。 public class UserInfo { public string UserName { get; set; }public string UserSex { get; set; }public string UserP…

利用瑞士军刀netcat建立连接并实现文件上传

实验环境&#xff1a; Kali:192.168.117.129 Windows10:192.168.135.142 第一步&#xff1a;建立连接 在Windows上下载netcat(官网搜索) 下载好之后在netcat目录打开cmd进入小黑屏 实验一&#xff1a;建立虚拟机与主机的连接 命令&#xff1a; Kali:nc 192.168.135.144…

观成科技:白象组织BADNEWS木马加密通信分析总结报告

概述 白象&#xff0c;又名Hangover、Patchwork、摩诃草等&#xff0c;该组织主要针对中国、巴基斯坦等亚洲地区国家进行网络间谍活动&#xff0c;攻击目标以政府机构、科研教育领域为主。 自16年起&#xff0c;该APT组织一直持续使用攻击武器BADNEWS开展攻击活动&#xff0c…

C++:变量和常量(3)

变量 什么是变量&#xff1a;变量就是一个装东西的盒子 通俗&#xff1a;变量是用于存放数据的容器。我们通过变量名获取数据&#xff0c;甚至数据可以修改 变量的作用&#xff1a;给指定的内存空间起名&#xff0c;后期通过起的名字就可以调用整个内存空间 定义变量的格式 &a…

Jenkins--在Linux上使用Docker安装

一、Jenkins 简介 Jenkins是一个流行的开源自动化服务器&#xff0c;用于持续集成和持续交付&#xff08;CI/CD&#xff09;。Jenkins的核心功能主要包括以下几点&#xff1a; 持续集成&#xff1a;Jenkins可以监控版本控制系统&#xff08;如Git、SVN&#xff09;中的代码变…

pytorch+tensorboard

安装依赖 pip install teorboard pip install torch_tb_profiler了解teorboard 记录并可视化标量[组]、图片[组]。 如何使用 第一步:构建模型,记录中间值,写入summarywriter 每次写入一个标量add_scalar 比如: from torch.utils.tensorboard import SummaryWriter wr…

三、阅读器开发--4、阅读器目录、全文搜索功能开发

1、阅读器目录 1.1、实现目录 先实现目录的布局 定义一个蒙版&#xff0c;充满整个屏幕浮在阅读器上方&#xff0c;左侧为目录右侧为背景&#xff0c;目录下方包含一个tab&#xff0c;点击后会切换不同的内容&#xff0c;这里tab是目录、书签&#xff0c;这里可以通过如下的…

华为设备配置攻击防范

组网需求 如图1所示&#xff0c;如果局域网内存在Hacker向RouterA发起畸形报文攻击、分片报文攻击和泛洪攻击&#xff0c;将会造成RouterA瘫痪。为了预防这种情况&#xff0c;管理员希望通过在RouterA上部署各种攻击防范措施来为用户提供安全的网络环境&#xff0c;保障正常的…