当前位置: 首页 > news >正文

设计模式—观察者模式(Observer)

目录

思维导图

一、什么是观察者模式?

二、有什么优点吗?

三、有什么缺点吗?

四、什么时候使用观察者模式?

五、代码展示

①、双向耦合的代码

②、解耦实践一

③、解耦实践二

④、观察者模式

六、这个模式涉及到了哪些知识点?


思维导图

一、什么是观察者模式?

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

观察者类似于卧底这样一个角色。在上班的时候,难免会有人趁老板不在的时候做一些工作之外的事情,例如炒炒股,看看NBA之类的,那如何应对老板突然回来这件事情呢?我们就需要卧底这样一个人给我们放风,老板一回来就通知这些人“老板回来了”。这其实就是一种观察者模式

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

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

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

ConcreteObserver类:具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。

二、有什么优点吗?

观察者模式所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。满足依赖倒转原则

三、有什么缺点吗?

如果观察者很多的话,一个一个的通知会影响效率

四、什么时候使用观察者模式?

当一个对象的改变需要同时改变其他对象的时候。

而且它不知道具体有多少对象有待改变时,应该考虑使用观察者模式。


五、代码展示

场景:小菜公司的同事在老板外出的期间偷偷地通过网页看股票行情,但是一不小心老板就回来了,让老板看到工作的时候做这些总是不太好的,如果避免这样的情况呢?就需要前台秘书这样的一个卧底,老板一回来了,前台秘书童子喆就拨了个电话告诉同事。但有一次因为老板回来直接就找童子喆做一些其他事情,童子喆就没来得及打电话,导致同事就没被通知到“老板回来了”

①、双向耦合的代码

	//前台秘书类class Secretary{//同事列表private IList<StockObserver> observers = new List<StockObserver>();    //IList接口,List泛型,集合数据类型是StockObserverprivate string action;                  //成员变量//构造方法public Secretary() { }//增加public void Attach(StockObserver observer){observers.Add(observer);           //向集合里面添加同事}//通知public void Notify(){foreach (StockObserver o in observers)    //foreach遍历集合:数据类型  变量名 in 遍历的集合o.Update();                           //一个一个的给同事通知}//前台状态public string SecretaryAction{get { return action; }                //get访问器set { action = value; }             //set访问器}}//看股票同事类class StockObserver{private string name;            //字符串成员变量private Secretary sub;          //前台秘书类类型成员变量public StockObserver(string name, Secretary sub)    //构造方法{this.name = name;           //赋值this.sub = sub;}public void Update()    //通知{Console.WriteLine("{0}{1}关闭股票行情,继续工作!", sub.SecretaryAction, name); //要通知的语句}} 

客户端代码:

//前台小姐童子喆
Secretary tongzizhe = new Secretary();//看股票的同事
StockObserver tongshi1 = new StockObserver("魏关姹", tongzizhe);
StockObserver tongshi2 = new StockObserver("易管查", tongzizhe);//前台记下了两位同事
tongzizhe.Attach(tongshi1);
tongzizhe.Attach(tongshi2);//发现老板回来
tongzizhe.SecretaryAction = "老板回来了";//通知两个同事
tongzizhe.Notify();Console.ReadKey ();

问题:前台类和看股票者类之间互相耦合。

②、解耦实践一

抽象观察类


abstract class Observer
{protected string name;protected Secretary sub;public Observer(string name, Secretary sub)     //有参的构造方法{this.name = name;this.sub = sub;}//通知public abstract void Update();
}

看股票的同事

class StockObserver : Observer
{//继承父类的构造方法public StockObserver(string name, Secretary sub) : base(name, sub) { }public override void Update(){Console.WriteLine("{0}{1} 关闭股票行情,继续工作!", sub.SecretaryAction, name);}
}

看NBA的同事

class NBAObserver : Observer
{public NBAObserver(string name, Secretary sub) : base(name, sub) { }public override void Update(){Console.WriteLine("{0}{1} 关闭NBA直播,继续工作!", sub.SecretaryAction, name);}
}

   前台秘书类

	class Secretary{private IList<Observer> observers = new List<Observer>();   //集合private string action;                                      //成员变量//增加public void Attach(Observer observer)    //针对抽象编程,减少了与具体类的耦合{observers.Add(observer);}//减少public void Detach(Observer observer)    //针对抽象编程,减少了与具体类的耦合{observers.Remove(observer);}//通知public void Notify(){foreach (Observer o in observers)o.Update();}//前台状态public string SecretaryAction     //属性{get { return action; }set { action = value; }}} 

客户端代码

 //前台小姐童子喆
Secretary tongzizhe = new Secretary();//看股票的同事
StockObserver tongshi1 = new StockObserver("魏关姹", tongzizhe);
StockObserver tongshi2 = new StockObserver("易管查", tongzizhe);//前台记下了两位同事
tongzizhe.Attach(tongshi1);
tongzizhe.Attach(tongshi2);//发现老板回来
tongzizhe.SecretaryAction = "老板回来了";//通知两个同事
tongzizhe.Notify();Console.ReadKey ();

③、解耦实践二

    通知者接口

	interface Subject{void Attach(Observer observer);     //增加void Detach(Observer observer);     //减少void Notify();                      //通知string SubjectState                 //前台状态{get;set;}}

    老板

	class Boss : Subject{//同事列表private IList<Observer> observers = new List<Observer>();private string action;//增加public void Attach(Observer observer){observers.Add(observer);}//减少public void Detach(Observer observer){observers.Remove(observer);}//通知public void Notify(){foreach (Observer o in observers)o.Update();}//前台状态public string SubjectState{get { return action; }set { action = value; }}}

前台秘书类

	class Secretary{//同事列表private IList<Observer> observers = new List<Observer>();private string action;//增加public void Attach(Observer observer){observers.Add(observer);}//减少public void Detach(Observer observer){observers.Remove(observer);}//通知public void Notify(){foreach (Observer o in observers)o.Update();}//前台状态public string SubjectState{get { return action; }set { action = value; }}}

抽象观察者

	abstract class Observer{protected string name;          //成员变量,姓名protected Subject sub;          //成员变量,通知者public Observer(string name, Subject sub)   //构造方法{this.name = name;                   //赋值this.sub = sub;}public abstract void Update();}

看股票的同事

	class StockObserver : Observer{public StockObserver(string name, Subject sub) : base(name, sub) { }public override void Update(){Console.WriteLine("{0}{1} 关闭股票行情,继续工作!", sub.SubjectState, name);}}#endregion

客户端代码

//老板胡汉三
Boss huhansan = new Boss();//看股票的同事
StockObserver tongshi1 = new StockObserver("魏关姹", huhansan);
//看NBA的同事
StockObserver tongshi2 = new StockObserver("易管查", huhansan);huhansan.Attach(tongshi1);
huhansan.Attach(tongshi2);huhansan.Detach(tongshi1);            //魏关姹其实是没有被老板通知到,所以减去//老板回来
huhansan.SubjectState = "我胡汉三回来了";
//发出通知
huhansan.Notify();Console.ReadKey();

④、观察者模式

Subject:抽象通知者/主题,一般用一个抽象类或者一个接口实现.它把所有对观察者对象的引用保存在一个聚集里,每个主题都可以由任何数量的观察者.抽象主题提供一个接口,可以增加和删除观察者对象

	abstract class Subject{private IList<Observer> observers = new List<Observer>();//增加观察者public void Attach(Observer observer){observers.Add(observer);}//删除观察者public void Detach(Observer observer){observers.Remove(observer);}//通知public void Notify(){foreach (Observer o in observers)o.Update();}}

Observer类:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己.这个接口叫做更新接口.抽象观察者一般用一个抽象类或者一个接口实现.更新接口通常包含一个Update()方法,这个方法叫做更新方法.

abstract class Observer
{public abstract void Update();
}

ConcreteSubject:具体主题/具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知.具体主题角色同一个具体子类实现.

class ConcreteSubject : Subject
{private string subjectState;//具体被观察者状态public string SubjectState{get { return subjectState; }set { subjectState = value; }}
}

// ConcreteObserver:具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调.具体观察者角色可以保存一个指向具体主题对象的引用.具体观察者角色通常用一个具体子类实现.

	class ConcreteObserver : Observer{//成员变量private string name;private string observerState;private ConcreteSubject subject;//构造方法public ConcreteObserver(ConcreteSubject subject,string name){this.subject = subject;    //赋值this.name = name;}//重写抽象类Update方法public override void Update(){observerState = subject.SubjectState;     //赋值Console.WriteLine("观察者{0}的新状态是{1}", name, observerState);  //控制台输出结果}//具体观察者状态public ConcreteSubject Subject {get { return subject; }set { subject = value; }}}

观察者模式的动机是将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就需要维护相关对象间的一致性.我们不希望为了维持一致性而使各类紧密耦合,这样会给维护\扩展和重用都带来不便.


六、这个模式涉及到了哪些知识点?

①、一个类里面有哪些东西?

②、字段和属性

字段

是什么?与类相关的变量;

干什么的?用来保存数据

属性

是什么?一个方法或一对方法

什么作用?具有两个方法,get、set访问器,读、写值

  • get访问器:返回与声明的属性相同的数据类型,表示的意思是调用时可以得到内部字段的值或引用;
  • set访问器:没有显式设置参数,但它有一个隐式参数,用关键字value表示,它的作用是调用属性时可以给内部的字段或引用赋值

显示和隐式字段初始化

字段的初始值必须是编译时可确定的。

如果没有初始化语句,字段的值会被编译器设为默认值,默认值由字段的类型决定。每种值类型的默认值都是0,bool型是false,引用类型默认为null。

class MyClass、
{int F1;	         //初始化为0     -值类型string F2;		 //初始化为null  -引用类型int F3 =25;		 //初始化为25string F4="abcd";  //初始化为“abcd”//声明多个字段,东逗号分隔int F1,F3 =25;string F2,F4="abcd";
}

③、访问修饰符

什么作用?指定程序的其他部分如何访问成员

有哪些?

  • private:私有的,只在类的内部可访问,成员默认是这个
  • public:公有的,对任何类可访问
  • protected:受保护的,只允许该类的派生类访问
  • internal:内部的,同一项目所有类可访问

④、构造方法

目的:对类进行初始化

特点:与类同名,无返回值、无void、在new时候调用

所有的类都有构造方法,不带参数的构造方法称为“默认构造方法”,如果你不编码则系统默认生成空的构造方法。若定义了新的构造方法,那么默认的构造方法就会失效。

⑤、方法重载

目的:在不改变原方法的基础上,新增功能

特点:一同二不同:多个方法名相同、参数类型/个数不同

class Animal
{private string name;//方法重载:方法名相同、数据类型/个数不同public Animal(){}          //无参的构造方法public Animal(string name) //有参的构造方法{this.name = name;}
}

⑥、foreach循环

连续访问数组中的每一个元素。

//语法
foreach(Type Identifier in ArrayName)Statement//实例
int[] arr1 = {10,11,12,13};foreach(int item in arr1)Console.WriteLine("Item Value:{0}",item);

⑦、List泛型集合

  • arrayList集合:不知道存什么类型,不知道存多少个
  • List:知道存什么类型,不知道存多少个。就是为了专门处理某种类型,在尖括号中写什么类型,这个集合就变成了什么类型的集合
  • 添加数据、插入数据、索引访问数据都是这个类型的,不用考虑所有的转换问题
static void Main(string[] args)
{List<int> list = new List<int>();     //实例化int类型//随机的往这个List集合中添加十个数字,不能重复,求和,求最大值,求最小值,求平均值Random r = new Random();int num = 0;while (list.Count !=10){num = r.Next(1, 100);if (!list.Contains (num)){list.Add(num);}}Console.WriteLine("最大值:{0}",list.Max ());Console.WriteLine("最小值:{0}",list.Min ());Console.WriteLine("和为:{0}",list .Sum ());Console.WriteLine("平均值为:{0}",list.Average ());Console.ReadKey();List<string> listStr = new List<string>();   //实例化string类型listStr.Add("哈哈,小杨又变帅了");
}

⑧、数组、ArrayList和List三者之间的对比:

⑨、抽象类

目的:抽取相同代码,实现封装思想

特点:

  • 抽象类不能实例化;
  • 抽象方法是必须被子类重写的方法;
  • 如果类中包含抽象方法,那么类就必须定义为抽象类,不论是否还包含其他一般方法

⑩、重写

将父类实现替换为它自己的实现

虚成员

抽象成员

关键字

virtual

abstract

实现体

有实现体

没有实现体,被分号取代

在派生类中被覆写

可重写,也可不重写,使用override

必须被重写,使用override

⑩①、接口

接口提出了一种契约(或者说规范),让使用接口的程序设计人员必须严格遵守接口提出的约定。接口就可以看做是这种标准,它强制性地要求派生类必须实现接口约定的规范,以保证派生类必须拥有某些特性。

特点:

  • 不能实例化;
  • 不能有构造方法和字段;
  • 不能有修饰符;
  • 接口包含(事件、索引器、方法、属性);
  • 不包含方法的实现;
  • 实现接口的类必须实现接口中的所有方法和属性

⑩②、六大原则:依赖倒转原则

-高层模块不应该依赖底层模块。两个都应该依赖抽象(接口/抽象类)。

-抽象不应该依赖细节(具体类)。细节应该依赖抽象。

我现在要设计一个汽车,我先设计汽车大概的样子,先设计轮胎,根据轮胎在设计底盘,根据底盘在设计车身。现在我想要修改轮胎的尺寸,是不是就需要修改底盘,修改车身,整个全部都得修改?如果我们倒过来看,在设计车身,根据车身在设计底盘,根据底盘在设计轮胎,这样的话如果轮胎的尺寸变了,也不会影响到其他的部分

谁也不要依赖谁,除了约定的接口,大家都可以灵活自如。

针对书上所举的例子:无论主板、CPU、内存、硬盘都是在针对接口设计的。CPU作为主板上一个可移动的、可扩展的部分,在设计主板的时候只需要把接口定义好,内部再复杂我也不让外界知道,而主板只需要预留与CPU阵脚的插槽就可以了。内存、硬盘、显卡都是如此,哪部分坏了直接更换那部分就行了,而不会导致整个主板全部都要换。

 

⑩③、六大关系

  • 依赖:使用关系,一个类的使用需要另一个类的协助

实现:局部变量、构造方法的参数、静态方法的调用

图形:虚线+箭头,指向被拥有者

Animal {Public Water Grownup(Water water) {return null;}
}

  • 关联:拥有关系,一个类需要使用另一个类的属性和方法

实现:成员变量

图形:实线+箭头

class Water {public Climate m_Climate;public Water(){}
}class Climate {public Climate() {}
}

  • 聚合:整体和部分的关系,部分不能脱离整体而单独存在

实现:成员变量+构造方法的参数赋值

图形:实线+空心菱形,菱形指向整体

class GooseGroup {public Goose goose;Public GooseGroup(Goose goose) {this.goose = goose;}
}
class Work
{private State current;public Work(){current = new ForenoonState();}
}
  • 继承:子类继承父类

实现:子类:父类

图形:实线+空心三角形,箭头指向父类

class Cat:Animal
{}

  • 实现:类和接口的关系,类实现接口的所有特征

实现:类:接口

图形:虚线+空心三角,箭头指向接口

Class WideGoose:Ifly
{ }

相关文章:

设计模式—观察者模式(Observer)

目录 思维导图 一、什么是观察者模式&#xff1f; 二、有什么优点吗&#xff1f; 三、有什么缺点吗&#xff1f; 四、什么时候使用观察者模式&#xff1f; 五、代码展示 ①、双向耦合的代码 ②、解耦实践一 ③、解耦实践二 ④、观察者模式 六、这个模式涉及到了哪些…...

分类算法系列③:模型选择与调优 (Facebook签到位置预测)

目录 模型选择与调优 1、介绍 模型选择&#xff08;Model Selection&#xff09;&#xff1a; 调优&#xff08;Hyperparameter Tuning&#xff09;&#xff1a; 本章重点 2、交叉验证 介绍 为什么需要交叉验证 数据处理 3、⭐超参数搜索-网格搜索(Grid Search) 介绍…...

PCL RANSAC分割提取多个空间圆

目录 一、概述二、代码实现三、结果展示1、原始数据2、提取结果四、测试数据本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、概述 使用PCL分割提取多个空间圆,其核心原理仍然是RANSAC拟合空间圆,这里只是做简单修改…...

Java八股文学习笔记day01

01.和equals区别 对于字符串变量来说&#xff0c;使用""和"equals"比较字符串时&#xff0c;其比较方法不同。""比较两个变量本身的值&#xff0c;即两个对象在内存中的首地址&#xff0c;"equals"比较字符串包含内容是否相同。 对于非…...

vant的NavBar导航栏可以自定义背景图片吗

可以的&#xff0c;Vant的NavBar导航栏提供了一个background-image属性&#xff0c;可以设置自定义背景图片。例 如&#xff1a; <van-nav-bar title"标题" left-text"返回" left-arrow background-image"url(https://example.com/image.jpg)&qu…...

深入浅出AXI协议(5)——数据读写结构读写响应结构

目录 一、前言 二、写选通&#xff08;Write strobes&#xff09; 三、窄传输&#xff08;Narrow transfers&#xff09; 1、示例1 2、示例2 四、字节不变性&#xff08;Byte invariance&#xff09; 五、未对齐的传输&#xff08;Unaligned transfers&#xff09; 六…...

IntelliJ Idea开发Vue遇到的几个问题

IntelliJ Idea开发Vue遇到的几个问题 确保 idea已安装插件【Vue.js】 问题1&#xff1a;ts方法错误 或 提示导入 import xxx.vue标红 解决办法&#xff1a;在 env.d.ts中添加以下代码(若无此文件&#xff0c;重新创建)&#xff1a; /* eslint-disable */ declare module *.…...

sql查找最晚一天/日期最大的一条记录 两种方法

例&#xff1a;查找最晚入职员工的所有信息 建表&#xff1a; CREATE TABLE employees ( emp_no int(11) NOT NULL, birth_date date NOT NULL, first_name varchar(14) NOT NULL, last_name varchar(16) NOT NULL, gender char(1) NOT NULL, hire_date date NOT NULL, PRIMA…...

详解python的

详解& 在Python中&#xff0c;使用&符号可以求取两种数据类型的交集&#xff1a; 集合&#xff08;Set&#xff09;&#xff1a;你可以使用&来计算两个集合的交集。例如&#xff1a; set1 {1, 2, 3, 4} set2 {3, 4, 5, 6} common_elements set1 & set2 pri…...

Modbus TCP通信笔记

目录 1 Modbus TCP 数据协议1.1 数据格式1.2 报文头(MBAP头)1.3 功能码1.4 Modbus 地址映射到 CPU 地址 2 Modbus TCP 通讯数据示例2.1 功能码01 读离散输出线圈2.2 功能码02 读离散输入线圈2.3 功能码03 读保持寄存器2.4 功能码04 读输入寄存器2.5 功能码05 写单个离散输出寄存…...

CIM和websockt-实现实时消息通信:双人聊天和消息列表展示

欢迎大佬的来访&#xff0c;给大佬奉茶 一、文章背景 有一个业务需求是&#xff1a;实现一个聊天室&#xff0c;我和对方可以聊天&#xff1b;以及有一个消息列表展示我和对方&#xff08;多个人&#xff09;的聊天信息和及时接收到对方发来的消息并展示在列表上。 项目框架概…...

useLayoutEffect和useEffect有什么作用?

useEffect 和 useLayoutEffect 都是 React 中的钩子函数,用于在组件渲染过程中执行副作用操作。它们的主要区别在于执行时机。 useEffect: useEffect 是异步执行的,它在浏览器渲染完成之后才执行。这意味着它不会阻塞浏览器的渲染过程,因此适合用于处理副作用,如数据获取、…...

django中配置使用websocket终极解决方案

django ASGI/Channels 启动和 ASGI/daphne的区别 Django ASGI/Channels 是 Django 框架的一个扩展&#xff0c;它提供了异步服务器网关接口&#xff08;ASGI&#xff09;协议的支持&#xff0c;以便处理实时应用程序的并发连接。ASGI 是一个用于构建异步 Web 服务器和应用程序…...

敦煌网、Jumia等跨境电商平台怎么测评(补单)留评?

评论的重要性是众所周知的&#xff0c;对于想要做卖家运营的人来说&#xff0c;它直接影响着产品的销量和排名 那么如何通过自养号测评来提升销量和排名呢&#xff1f; 我相信大家对这个问题已经有了一定的了解&#xff0c;拥有大量自养号可以通过这些号来通过关键词搜索、浏…...

uni-app之android离线打包

一 AndroidStudio创建项目 1.1&#xff0c;上一节演示了uni-app云打包&#xff0c;下面演示怎样androidStudio离线打包。在AndroidStudio里面新建空项目 1.2&#xff0c;下载uni-app离线SDK&#xff0c;离线SDK主要用于App本地离线打包及扩展原生能力&#xff0c;SDK下载链接h…...

【传输层】TCP -- 三次握手四次挥手 | 可靠性与提高性能策略

超时重传机制连接管理机制三次握手四次挥手滑动窗口拥塞控制延迟应答捎带应答面向字节流粘包问题TCP异常情况TCP小结基于TCP应用层协议理解 listen 的第二个参数 超时重传机制 主机A发送数据给B之后&#xff0c;可能因为网络拥堵等原因&#xff0c;数据无法到达主机B&#xff1…...

前端将UTC时间格式转化为本地时间格式~~uniapp写法

UTC时间格式是什么 首先我们先简单的了解一下&#xff1a;UTC时间&#xff08;协调世界时&#xff0c;Coordinated Universal Time&#xff09;使用24小时制&#xff0c;以小时、分钟、秒和毫秒来表示时间 HH:mm:ss.SSSHH 表示小时&#xff0c;取值范围为00到23。mm 表示分钟…...

说说Kappa架构

分析&回答 对于实时数仓而言&#xff0c;Lmabda架构有很明显的不足&#xff0c;首先同时维护两套系统&#xff0c;资源占用率高&#xff0c;其次这两套系统的数据处理逻辑相同&#xff0c;代码重复开发。 能否有一种架构&#xff0c;只需要维护一套系统&#xff0c;就可以…...

项目介绍:《Online ChatRoom》网页聊天室 — Spring Boot、MyBatis、MySQL和WebSocket的奇妙融合

在当今数字化社会&#xff0c;即时通讯已成为人们生活中不可或缺的一部分。为了满足这一需求&#xff0c;我开发了一个名为"WeTalk"的聊天室项目&#xff0c;该项目基于Spring Boot、MyBatis、MySQL和WebSocket技术&#xff0c;为用户提供了一个实时交流的平台。在本…...

Vue3 学习 组合式API setup语法糖 响应式 指令 DIFF(一)

文章目录 前言一、Composition Api二、setup语法糖三、响应式refreactive 四、其他一些关键点v-prev-oncev-memov-cloak 五、虚拟Dom五、diff算法 前言 本文用于记录学习Vue3的过程 一、Composition Api 我觉得首先VUE3最大的改变就是对于代码书写的改变&#xff0c;从原来选择…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...