C++设计模式_07_Bridge 桥模式
文章目录
- 1. 动机(Motivation)
- 2. 代码演示Bridge 桥模式
- 2.1 基于继承的常规思维处理
- 2.2 基于组合关系的重构优化
- 2.3 采用Bridge 桥模式的实现
- 3. 模式定义
- 4. 结构(Structure)
- 5. 要点总结
与上篇介绍的Decorator 装饰模式一样,Bridge 桥模式也属于典型的“单一职责”模式,在特性上也与Decorator 装饰模式存在很多类似,但也存在不同得到地方。
“单一职责”模式的主要特征为:“在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码
,这时候的关键是划清责任。”
1. 动机(Motivation)
-
由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个纬度的变化。
-
如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度?
2. 代码演示Bridge 桥模式
针对上面的理解还是需要回到代码进行理解。
2.1 基于继承的常规思维处理
下面的代码是一个简单的通信模块,实现的功能包括Login()、SendMessage()…等。
class Messager{
public:virtual void Login(string username, string password)=0;virtual void SendMessage(string message)=0;virtual void SendPicture(Image image)=0;virtual void PlaySound()=0;virtual void DrawShape()=0;virtual void WriteText()=0;virtual void Connect()=0;virtual ~Messager(){}
};
然后需要进行PC平台的设计,但是由于平台的不同,需要override PlaySound()、DrawShape()、WriteText()、Connect()
class PCMessagerBase : public Messager{
public:virtual void PlaySound(){//**********}virtual void DrawShape(){//**********}virtual void WriteText(){//**********}virtual void Connect(){//**********}
};
类似PC平台的设计,Mobile上的设计也需要对相应的功能override
class MobileMessagerBase : public Messager{
public:virtual void PlaySound(){//==========}virtual void DrawShape(){//==========}virtual void WriteText(){//==========}virtual void Connect(){//==========}
};
另外我们可能会有在不同平台出“精简版”、“完美版”的需求,例如,在PC平台中class PCMessagerLite : public PCMessagerBase
,其中实现了某些功能,而在class PCMessagerPerfect : public PCMessagerBase
,这个时候“完美版”在实现功能时会有更多的功能内容,但是最基本的是一样,都是调用PCMessagerBase的方法。同样在Mobile平台也是有“精简版”、“完美版”的需求,虽然平台不同,但是业务功能需求也是一样的。
class PCMessagerLite : public PCMessagerBase {
public:virtual void Login(string username, string password){PCMessagerBase::Connect();//........}virtual void SendMessage(string message){PCMessagerBase::WriteText();//........}virtual void SendPicture(Image image){PCMessagerBase::DrawShape();//........}
};class PCMessagerPerfect : public PCMessagerBase {
public:virtual void Login(string username, string password){PCMessagerBase::PlaySound();//********PCMessagerBase::Connect();//........}virtual void SendMessage(string message){PCMessagerBase::PlaySound();//********PCMessagerBase::WriteText();//........}virtual void SendPicture(Image image){PCMessagerBase::PlaySound();//********PCMessagerBase::DrawShape();//........}
};class MobileMessagerLite : public MobileMessagerBase {
public:virtual void Login(string username, string password){MobileMessagerBase::Connect();//........}virtual void SendMessage(string message){MobileMessagerBase::WriteText();//........}virtual void SendPicture(Image image){MobileMessagerBase::DrawShape();//........}
};class MobileMessagerPerfect : public MobileMessagerBase {
public:virtual void Login(string username, string password){MobileMessagerBase::PlaySound();//********MobileMessagerBase::Connect();//........}virtual void SendMessage(string message){MobileMessagerBase::PlaySound();//********MobileMessagerBase::WriteText();//........}virtual void SendPicture(Image image){MobileMessagerBase::PlaySound();//********MobileMessagerBase::DrawShape();//........}
};
整体代码如下:
class Messager{
public:virtual void Login(string username, string password)=0;virtual void SendMessage(string message)=0;virtual void SendPicture(Image image)=0;virtual void PlaySound()=0;virtual void DrawShape()=0;virtual void WriteText()=0;virtual void Connect()=0;virtual ~Messager(){}
};//平台实现class PCMessagerBase : public Messager{
public:virtual void PlaySound(){//**********}virtual void DrawShape(){//**********}virtual void WriteText(){//**********}virtual void Connect(){//**********}
};class MobileMessagerBase : public Messager{
public:virtual void PlaySound(){//==========}virtual void DrawShape(){//==========}virtual void WriteText(){//==========}virtual void Connect(){//==========}
};//业务抽象class PCMessagerLite : public PCMessagerBase {
public:virtual void Login(string username, string password){PCMessagerBase::Connect();//........}virtual void SendMessage(string message){PCMessagerBase::WriteText();//........}virtual void SendPicture(Image image){PCMessagerBase::DrawShape();//........}
};class PCMessagerPerfect : public PCMessagerBase {
public:virtual void Login(string username, string password){PCMessagerBase::PlaySound();//********PCMessagerBase::Connect();//........}virtual void SendMessage(string message){PCMessagerBase::PlaySound();//********PCMessagerBase::WriteText();//........}virtual void SendPicture(Image image){PCMessagerBase::PlaySound();//********PCMessagerBase::DrawShape();//........}
};class MobileMessagerLite : public MobileMessagerBase {
public:virtual void Login(string username, string password){MobileMessagerBase::Connect();//........}virtual void SendMessage(string message){MobileMessagerBase::WriteText();//........}virtual void SendPicture(Image image){MobileMessagerBase::DrawShape();//........}
};class MobileMessagerPerfect : public MobileMessagerBase {
public:virtual void Login(string username, string password){MobileMessagerBase::PlaySound();//********MobileMessagerBase::Connect();//........}virtual void SendMessage(string message){MobileMessagerBase::PlaySound();//********MobileMessagerBase::WriteText();//........}virtual void SendPicture(Image image){MobileMessagerBase::PlaySound();//********MobileMessagerBase::DrawShape();//........}
};void Process(){//编译时装配Messager *m =new MobileMessagerPerfect();
}
以上是一种编译式装配
的方式,上面代码的框架不难画出,得到如下图:
2.2 基于组合关系的重构优化
如果将平台实现列为n的话,将业务抽象列为m的话,整体类的数目就是1+n+m*n
,此处不像Decorator 装饰模式中Lite和Perfect会有组合的情况,这样就造成大量的类,并且在类中的方法也是存在重复的例如:
PCMessagerPerfect中的:
virtual void Login(string username, string password){PCMessagerBase::PlaySound();//********PCMessagerBase::Connect();//........}
MobileMessagerPerfect中的:
virtual void Login(string username, string password){MobileMessagerBase::PlaySound();//********MobileMessagerBase::Connect();//........}
上面的内容都是似曾相识的重复,这种重复也是结构性的重复:
以下内容都是相同的
//********
//........
不同的就是:PCMessagerBase::PlaySound();
和MobileMessagerBase::PlaySound();
,PCMessagerBase::Connect();
和MobileMessagerBase::Connect();
如果有Decorator 装饰模式基础的话可以发现可以使用继承转组合进行重构,例如将class PCMessagerPerfect : public PCMessagerBase { }
中的父类变为数据成员class PCMessagerPerfect { PCMessagerBase* messager }
,声明为指针是因为指针具有多态性,相应的Mobile平台的也进行修改。
class PCMessagerPerfect {PCMessagerBase* messager;public:virtual void Login(string username, string password){messager->PlaySound();//********messager->Connect();//........}virtual void SendMessage(string message){messager->PlaySound();//********messager->WriteText();//........}virtual void SendPicture(Image image){messager->PlaySound();//********messager->DrawShape();//........}
};class MobileMessagerPerfect {MobileMessagerBase* messager;
public:virtual void Login(string username, string password){messager->PlaySound();//********messager->Connect();//........}virtual void SendMessage(string message){messager->PlaySound();//********messager->WriteText();//........}virtual void SendPicture(Image image){messager->PlaySound();//********messager->DrawShape();//........}
};
从上面的代码可以看到,两个类不同的地方就是PCMessagerBase* messager;
和MobileMessagerBase* messager;
,他们两个来自于一个基类,因此可以改写为以下形式:
class PCMessagerPerfect {Messager* messager; //未来运行时可以new PCMessagerPerfect();public:virtual void Login(string username, string password){messager->PlaySound();//********messager->Connect();//........}virtual void SendMessage(string message){messager->PlaySound();//********messager->WriteText();//........}virtual void SendPicture(Image image){messager->PlaySound();//********messager->DrawShape();//........}
};class MobileMessagerPerfect {Messager* messager; //未来运行时可以new MobileMessagerPerfect();
public:virtual void Login(string username, string password){messager->PlaySound();//********messager->Connect();//........}virtual void SendMessage(string message){messager->PlaySound();//********messager->WriteText();//........}virtual void SendPicture(Image image){messager->PlaySound();//********messager->DrawShape();//........}
};
此时class PCMessagerPerfect和class PCMessagerPerfect已经没有什么区别了,他们的区别就是在未来运行时,编译时的代码就可以变为:
class MessagerPerfect{Messager* messager; //未来运行时可以new PCMessagerPerfect()等;public:virtual void Login(string username, string password){messager->PlaySound();//********messager->Connect();//........}virtual void SendMessage(string message){messager->PlaySound();//********messager->WriteText();//........}virtual void SendPicture(Image image){messager->PlaySound();//********messager->DrawShape();//........}
};class MessagerPerfect{Messager* messager; //未来运行时可以new MobileMessagerPerfect();
public:virtual void Login(string username, string password){messager->PlaySound();//********messager->Connect();//........}virtual void SendMessage(string message){messager->PlaySound();//********messager->WriteText();//........}virtual void SendPicture(Image image){messager->PlaySound();//********messager->DrawShape();//........}
};
这个时候发现两个类一模一样,这个时候只需要保留一个即可,同样的MessagerLite也是如法炮制,变为如下形式:
class MessagerLite{Messager* messager; //未来运行时可以new PCMessagerLite()等;public:virtual void Login(string username, string password){messager->Connect();//........}virtual void SendMessage(string message){messager->WriteText();//........}virtual void SendPicture(Image image){messager->DrawShape();//........}
};
此时整体代码变为如下:
class Messager{
public:virtual void Login(string username, string password)=0;virtual void SendMessage(string message)=0;virtual void SendPicture(Image image)=0;virtual void PlaySound()=0;virtual void DrawShape()=0;virtual void WriteText()=0;virtual void Connect()=0;virtual ~Messager(){}
};//平台实现class PCMessagerBase : public Messager{
public:virtual void PlaySound(){//**********}virtual void DrawShape(){//**********}virtual void WriteText(){//**********}virtual void Connect(){//**********}
};class MobileMessagerBase : public Messager{
public:virtual void PlaySound(){//==========}virtual void DrawShape(){//==========}virtual void WriteText(){//==========}virtual void Connect(){//==========}
};//业务抽象
class MessagerLite{Messager* messager; public:virtual void Login(string username, string password){messager->Connect();//........}virtual void SendMessage(string message){messager->WriteText();//........}virtual void SendPicture(Image image){messager->DrawShape();//........}
};class MessagerPerfect{Messager* messager; //未来运行时可以new PCMessagerPerfect()等;public:virtual void Login(string username, string password){messager->PlaySound();//********messager->Connect();//........}virtual void SendMessage(string message){messager->PlaySound();//********messager->WriteText();//........}virtual void SendPicture(Image image){messager->PlaySound();//********messager->DrawShape();//........}
};void Process(){//编译时装配Messager *m =new MobileMessagerPerfect();
}
此时可以发现 Messager* messager; //未来运行时可以new PCMessagerPerfect()等;
是不成立的,这是因为class PCMessagerBase是一个抽象类。
为什么说其是抽象类呢? 因为其只override了class Messager中的部分虚函数,另外一些没有override。这个问题如何解决呢?在子类中只使用到了基类class Messager的一部分函数,里面的两个部分的函数塞在一起是不合适的,应该将其拆分开。
class Messager{
public:virtual void Login(string username, string password)=0;virtual void SendMessage(string message)=0;virtual void SendPicture(Image image)=0;virtual ~Messager(){}
};//平台实现
class MessagerImp{
public:virtual void PlaySound()=0;virtual void DrawShape()=0;virtual void WriteText()=0;virtual void Connect()=0;virtual MessagerImp(){}
};//平台实现 n
class PCMessagerImp : public MessagerImp{
public:virtual void PlaySound(){//**********}virtual void DrawShape(){//**********}virtual void WriteText(){//**********}virtual void Connect(){//**********}
};class MobileMessagerImp : public MessagerImp{
public:virtual void PlaySound(){//==========}virtual void DrawShape(){//==========}virtual void WriteText(){//==========}virtual void Connect(){//==========}
};//业务抽象 m//类的数目:1+n+mclass MessagerLite :public Messager {Messager* messager; //未来运行时可以new PCMessagerLite()等;
public:virtual void Login(string username, string password){messagerImp->Connect();//........}virtual void SendMessage(string message){messagerImp->WriteText();//........}virtual void SendPicture(Image image){messagerImp->DrawShape();//........}
};class MessagerPerfect :public Messager {Messager* messager; //未来运行时可以new PCMessagerPerfect()等; public:virtual void Login(string username, string password){messagerImp->PlaySound();//********messagerImp->Connect();//........}virtual void SendMessage(string message){messagerImp->PlaySound();//********messagerImp->WriteText();//........}virtual void SendPicture(Image image){messagerImp->PlaySound();//********messagerImp->DrawShape();//........}
};
2.3 采用Bridge 桥模式的实现
上面也是继承转组合,当做到这里已经接近完美,同样的马丁福乐重构中讲到,如果同样的子类中有通用的字段,此处即为class MessagerLite :public Messager
和class MessagerPerfect :public Messager
中的Messager* messager;
,那么往上提到父类Messager
中,变为以下形式:
class Messager{
protected:MessagerImp* messagerImp;//...
public:virtual void Login(string username, string password)=0;virtual void SendMessage(string message)=0;virtual void SendPicture(Image image)=0;virtual ~Messager(){}
};class MessagerImp{
public:virtual void PlaySound()=0;virtual void DrawShape()=0;virtual void WriteText()=0;virtual void Connect()=0;virtual MessagerImp(){}
};//平台实现 n
class PCMessagerImp : public MessagerImp{
public:virtual void PlaySound(){//**********}virtual void DrawShape(){//**********}virtual void WriteText(){//**********}virtual void Connect(){//**********}
};class MobileMessagerImp : public MessagerImp{
public:virtual void PlaySound(){//==========}virtual void DrawShape(){//==========}virtual void WriteText(){//==========}virtual void Connect(){//==========}
};//业务抽象 m//类的数目:1+n+mclass MessagerLite :public Messager {public:virtual void Login(string username, string password){messagerImp->Connect();//........}virtual void SendMessage(string message){messagerImp->WriteText();//........}virtual void SendPicture(Image image){messagerImp->DrawShape();//........}
};class MessagerPerfect :public Messager {public:virtual void Login(string username, string password){messagerImp->PlaySound();//********messagerImp->Connect();//........}virtual void SendMessage(string message){messagerImp->PlaySound();//********messagerImp->WriteText();//........}virtual void SendPicture(Image image){messagerImp->PlaySound();//********messagerImp->DrawShape();//........}
};void Process(){//运行时装配MessagerImp* mImp=new PCMessagerImp();Messager *m =new Messager(mImp);
}
当然需要父类提供构造函数,去初始化MessagerImp* messagerImp;
字段,子类放一个构造函数去调用父类的构造函数即可,此处未写。
此时就比较完美,类的个数就变为1+n+m
,但是运行时还会有n*m
的功能,这里就是桥模式。
回过头来看,在第一个版本中放了不同的函数,有不同的变化方向,一个变化方向是平台实现(PC、Mobile),一个变化方向是业务抽象(Lite、Perfect),这两个不同的变化方向,带动的行为的多态的实现也应该是往不同的方向走,也就不应该放在一个类中。
这也就体现了动机(Motivation)
中提到的多维度的变化
。
3. 模式定义
将抽象部分(业务功能
)与实现部分(平台实现
)分离,使它们都可以独立地变化。
——《设计模式》GoF
4. 结构(Structure)
上图是《设计模式》GoF中定义的Bridge 桥模式的设计结构。结合上面的代码看图中最重要的是看其中稳定和变化部分,也就是下图中红框和蓝框框选的部分。
两个变化方向独立变化,而不是搅在一起变化。
5. 要点总结
-
Bridge模式使用
“对象间的组合关系”
解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。所谓抽象和实现沿着各自纬度的变化,即“子类化”它们。 -
Bridge模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个类只有一个变化的原因),复用性比较差。Bridge模式是比多继承方案更好的解决方法。(推荐一个单继承配合组合的模式)
-
Bridge模式的应用一般在
“两个非常强的变化维度”
,有时一个类也有多于两个的变化维度,这时可以使用Bridge的扩展模式。
相关文章:

C++设计模式_07_Bridge 桥模式
文章目录 1. 动机(Motivation)2. 代码演示Bridge 桥模式2.1 基于继承的常规思维处理2.2 基于组合关系的重构优化2.3 采用Bridge 桥模式的实现 3. 模式定义4. 结构(Structure)5. 要点总结 与上篇介绍的Decorator 装饰模式一样&…...
[JAVA版本] Websocket获取B站直播弹幕——基于直播开放平台
教程 B站直播间弹幕Websocket获取 — 哔哩哔哩直播开放平台 基于B站直播开放平台开放且未上架时,只能个人使用。 代码实现 1、相关依赖 fastjson2用于解析JSON字符串,可自行替换成别的框架。 hutool-core用于解压zip数据,可自行替换成别的…...

第一个 Python 程序
三、第一个 Python 程序 好了,说了那么多,现在我们可以来写一下第一个 Python 程序了。 一开始写 Python 程序,个人不太建议用专门的工具来写,不方便熟悉语法,所以这里我先用 Sublime Text 来写,后期可以…...

广告牌安全监测,保障户外广告牌的安全与稳定
随着城市的发展和现代化,广告牌已经成为城市风景的一部分。然而,随之而来的是广告牌安全问题,因为它们暴露在各种天气和环境条件下,一旦掉落,可能对人们的生命和财产造成威胁。广告牌安全监测有效的解决了这一问题&…...

分类预测 | MATLAB实现KOA-CNN-GRU开普勒算法优化卷积门控循环单元数据分类预测
分类预测 | MATLAB实现KOA-CNN-GRU开普勒算法优化卷积门控循环单元数据分类预测 目录 分类预测 | MATLAB实现KOA-CNN-GRU开普勒算法优化卷积门控循环单元数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现KOA-CNN-GRU开普勒算法优化卷积门控循环单…...

进来了解实现官网搜索引擎的三种方法
做网站的目的是对自己的品牌进行推广,让越来越多的人知道自己的产品,但是如果只是做了一个网站放着,然后等着生意找上门来那是不可能的。在当今数字时代,实现官网搜索引擎对于提升用户体验和推动整体性能至关重要。搜索引擎可以帮…...

OpenCV3-Python(7)模板匹配和霍夫检测
模板匹配 膜版匹配不能匹配尺度变换和视角变换的图像 图片中查找和模板相似度最高的图像 计算相似程度最高的位置 res cv.matchTemplate(img , template, method) 该方法返回一个类似灰度图的东西,如果用的相关匹配,那么亮的地方就是可能匹配上的地方 …...

[C++11]花括号{}、initializer_list、auto、decltype
文章目录 1.花括号{ }的扩展2.initializer_list3.auto4.decltype5.容器的增加5.1array[useless]5.2forward_list[useless]5.3unordered_map/unordered_set5.4统一增加 6.知乎文章 1.花括号{ }的扩展 int main() {//C98花括号{ }支持 1.数组 2.结构体struct Point{int _x;int _…...

在Android平板上使用code-server公网远程Ubuntu服务器编程
文章目录 1.ubuntu本地安装code-server2. 安装cpolar内网穿透3. 创建隧道映射本地端口4. 安卓平板测试访问5.固定域名公网地址6.结语 1.ubuntu本地安装code-server 准备一台虚拟机,Ubuntu或者centos都可以,这里以VMwhere ubuntu系统为例 下载code server服务,浏览器…...
宝塔上安装mysql版本比较和区别
在宝塔上安装MySQL时,几个主要版本之间的区别主要在于性能、功能和安全性。 MySQL Community Server(社区版本):这是MySQL的开源免费版本,由社区支持,但不提供官方技术支持。这个版本对一般用户来说可能有…...

uniapp微信小程序自定义封装分段器。
uniapp微信小程序自定义封装分段器。 话不多说先上效果 这里我用的是cil框架 vue3 下面贴代码 组价代码: <template><view class"page"><viewv-for"(item, index) in navList":key"index"click"changeNav(ind…...

文心一言 VS 讯飞星火 VS chatgpt (111)-- 算法导论10.2 2题
二、用go语言,用一个单链表 L实现一个栈。要求操作 PUSH和 POP 的运行时间仍为 O(1)。 文心一言: 在 Go 语言中,我们可以用结构体来实现一个单链表,然后再用栈的相关操作。 以下是一个可能的实现方式: package mai…...

小程序中使用echarts的相关配置以及折线图案例(简单易懂)
第一步:引入echarts文件--此文件需要下载: 下载地址:点击此处进行下载echarts文件 点击Download ZIP下载压缩包,注意:e-canvas是我从完整的文件中剥离出来的有用的,不会影响项目。 第二步:把整…...
前端面试回答不好的问题总结
vue生命周期: beforeCreated、created、beforeMount、mount、beforeUptade、uptade、beforeDestroy、destroyed、 Activated、Deactivated 闭包: ECMAScript中,闭包指的是: 从理论角度:所有的函数。因为它们都在创…...
漏洞预警|CVE-2023-38545 Curl 和 libcurl 堆缓冲区溢出漏洞
项目介绍 libcurl是一个跨平台的网络协议库,支持http、https、ftp等多种协议。 项目地址 https://github.com/curl/curl/releases 影响版本 7.69.0-8.3.0 漏洞分析 漏洞成因在于使用SOCKS5代理过程中造成的溢出。当Curl程序使用 SOCKS5代理时,设置…...

【Java 进阶篇】HTML 语义化标签详解
HTML(HyperText Markup Language)是构建Web页面的标准语言。在HTML中,标签(tag)是用于定义页面结构和内容的关键元素。在构建网页时,了解如何正确使用HTML标签是非常重要的,因为它们不仅影响页面…...
【思维构造】Element Extermination—CF1375C
Element Extermination—CF1375C 参考文章 思路 若 a 1 < a n a_1<a_n a1<an, 初始时 a 2 , . . . , a n − 1 a_2, ..., a_{n-1} a2,...,an−1 这 n − 2 n-2 n−2 个元素中大于 a 1 a_1 a1 中的元素都能通过 a 1 a_1 a1 而被删除&…...
CSP模拟53联测15 D. 子序列
CSP模拟53联测15 D. 子序列 文章目录 CSP模拟53联测15 D. 子序列题目大意思路code 题目大意 (seq / 3s / 512 MiB) 给定一个长为 n n n 的仅有小写英文字母构成字符串 S S 1 S 2 ⋯ S n SS_1S_2\cdots S_n SS1S2⋯Sn。我们定义一个字符串是好…...
iceberg-flink 十一:在dlink代码中建表增加catalog地址。
一:catalog 是存储元数据的地方。 二:表中增加catalog地址’ 当我们映射iceberg表的时候,增加了地址,就会成功映射到表 CREATE CATALOG dk_empower WITH(typeiceberg,catalog-typehadoop,warehousehdfs://cluster/iceberg/war…...

多列等高实现
预期效果 多列等高,左右两列高度自适应且一样,分别设置不同背景色效果预览: 分别由6种方法实现 1、使用padding + margin + overflow 实现多列等高效果,具有良好的兼容性; 2、border实现多列等高,左边框宽度为200px,左列浮动,伪元素清除浮动; 3、父元素线性渐变背景色…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...