C++笔记之设计模式:setter函数、依赖注入
C++笔记之设计模式:setter函数、依赖注入
参考笔记:
1.C++笔记之静态成员函数可以在类外部访问私有构造函数吗?
2.C++笔记之设计模式:setter函数、依赖注入
3.C++笔记之两个类的实例之间传递参数——通过构造函数传递类对象的方法详细探究
4.C++笔记之智能指针和单例、依赖注入结合使用
5.C++笔记之两个类的实例之间传递参数的各种方法
code review!
文章目录
- C++笔记之设计模式:setter函数、依赖注入
- 1.概念
- 2.基本示例
- 3.setter函数
- 4.基本示例+setter函数构成依赖注入
- 5.概念——ChatGpt
- 6.构造函数注入示例
- 7.接口注入示例
- 8. 构造函数注入的使用场景和用途
- 9.接口注入的使用场景和用途
- 10.使用一个简单的业务逻辑来演示构造函数注入和接口注入的使用场景。
- 10.1.构造函数注入示例
- 10.2.接口注入示例
- 11.附加知识:SOLID设计原则
- 12.附加知识:依赖倒置原则
- 13.一个图形绘制应用程序。我们将创建一个图形类(Shape),并通过依赖注入来注入不同的绘制器(Drawer)来绘制不同的图形。
1.概念
依赖注入(Dependency Injection,DI)是一种软件设计模式,用于管理和解决组件之间的依赖关系。在传统的编程中,一个对象通常需要在自身内部创建或获取其所依赖的其他对象,这可能会导致紧密耦合的代码,使得代码难以测试、难以维护和难以扩展。依赖注入的目标是通过从外部传递依赖项来解耦组件,提高代码的可测试性、可维护性和灵活性。
依赖注入的主要思想是,一个组件(被称为"受注入对象")不应该负责创建或获取其依赖的对象。相反,这些依赖应该由外部实例化,并通过构造函数、方法参数、属性等方式注入到受注入对象中。这种方式可以在不修改受注入对象的情况下,灵活地替换依赖项的具体实现,以及在测试时传递模拟对象。
依赖注入可以分为以下几种形式:
-
构造函数注入:通过构造函数将依赖项传递给受注入对象。这是最常见的依赖注入方式。通过构造函数,依赖关系在对象创建时就被传递,并在整个对象生命周期中保持稳定。
-
方法参数注入:通过方法的参数将依赖项传递给对象的方法。这在需要特定依赖项执行特定操作的情况下非常有用。
-
属性注入:通过公开的属性将依赖项传递给对象。这种方式可能导致依赖关系的意外更改,因此在使用时需要小心。
-
接口注入:通过接口或抽象类定义依赖项,然后将具体实现传递给对象。这种方式允许在运行时替换依赖项的具体实现,实现多态性。
依赖注入的优势包括:
-
解耦和灵活性:减少了组件之间的紧耦合,使得代码更加灵活、可维护和易于扩展。
-
可测试性:可以轻松地传递模拟对象或桩对象,以进行单元测试,从而提高代码的测试覆盖率。
-
可读性:依赖关系在代码中被明确地传递,使代码更易于理解。
简单理解来说就是当依赖的某个对象是通过外部来注入,而不是自己创建。
2.基本示例
3.setter函数
4.基本示例+setter函数构成依赖注入
代码
class Tools {
public:virtual void doWork() = 0;
};class Hammer : public Tools {
public:void doWork() override {std::cout << "use hammer" << std::endl;}
};class Axe : public Tools {
public:void doWork() override {std::cout << "use Axe" << std::endl;}
};class Human {
public:Human(Tools& t) : tools(t) {}void doWork() {tools.doWork();}Tools& tools;
};void MakeHuman() {Hammer hammer;Human human1(hammer);human1.doWork();Axe axe;Human human2(axe);human2.doWork();
}int main() {MakeHuman();return 0;
}
5.概念——ChatGpt
6.构造函数注入示例
代码
#include <iostream>class Dependency {
public:void DoSomething() {std::cout << "Dependency is doing something." << std::endl;}
};class Service {
public:Service(Dependency* dependency) : dependency_(dependency) {}void UseDependency() {std::cout << "Service is using dependency." << std::endl;dependency_->DoSomething();}private:Dependency* dependency_;
};int main() {Dependency dependency;Service service(&dependency);service.UseDependency();return 0;
}
7.接口注入示例
代码
#include <iostream>class IDependency {
public:virtual void DoSomething() = 0;
};class Dependency : public IDependency {
public:void DoSomething() override {std::cout << "Dependency is doing something." << std::endl;}
};class Service {
public:Service(IDependency* dependency) : dependency_(dependency) {}void UseDependency() {std::cout << "Service is using dependency." << std::endl;dependency_->DoSomething();}private:IDependency* dependency_;
};int main() {Dependency dependency;Service service(&dependency);service.UseDependency();return 0;
}
8. 构造函数注入的使用场景和用途
构造函数注入是一种通过类的构造函数将依赖项传递给类的方式。这种方式适用于以下情况:
-
类需要一个稳定的依赖关系:通过构造函数注入,依赖项在对象创建时被设置,然后在整个对象生命周期内保持不变,确保了稳定的依赖关系。
-
松耦合和可测试性:依赖项的传递通过构造函数进行,使得类与具体的依赖实现解耦,从而提高了代码的可测试性和可维护性。
-
代码可读性:通过构造函数明确地传递依赖项,使得类的依赖关系更加明确和清晰。
-
依赖的外部控制:通过构造函数注入,外部代码可以在创建对象时决定传递的依赖项,从而实现对依赖的更好控制。
9.接口注入的使用场景和用途
接口注入是通过使用接口或抽象类定义依赖关系,然后传递具体实现的方式。这种方式适用于以下情况:
-
多态性和扩展性:接口注入允许在运行时决定使用的具体实现,从而实现多态性。这对于在不修改现有代码的情况下扩展应用程序非常有用。
-
模块替换:通过传递不同的实现,可以轻松替换具体的依赖项,从而实现模块的替换和重用。
-
依赖反转:通过依赖接口而不是具体实现,实现了依赖反转的原则,即高层模块不依赖于低层模块的具体实现细节。
-
解耦和灵活性:接口注入减少了类之间的紧耦合,从而提高了代码的灵活性和可维护性。
总之,构造函数注入和接口注入都是实现依赖注入的有效方式,可以根据项目需求选择适当的方式。构造函数注入适用于稳定的依赖关系和明确的依赖项传递,而接口注入适用于多态性、扩展性和模块替换的需求。无论使用哪种方式,依赖注入的目标是减少紧耦合,提高代码的可测试性、可维护性和灵活性。
10.使用一个简单的业务逻辑来演示构造函数注入和接口注入的使用场景。
我们将创建一个模拟的报告生成系统,其中包括一个报告生成器和一个数据源。
业务逻辑:
我们有一个报告生成器(ReportGenerator),它依赖于一个数据源(DataSource)。报告生成器通过数据源获取数据,并生成报告。
10.1.构造函数注入示例
代码
#include <iostream>
#include <string>// 数据源类,提供获取数据的方法
class DataSource {
public:std::string GetData() {return "Data from the data source.";}
};// 报告生成器类,依赖于数据源
class ReportGenerator {
public:// 构造函数,接收一个数据源对象作为依赖ReportGenerator(DataSource* dataSource) : dataSource_(dataSource) {}// 生成报告的方法void GenerateReport() {// 使用数据源获取数据std::string data = dataSource_->GetData();std::cout << "Generating report with data: " << data << std::endl;}private:DataSource* dataSource_; // 数据源对象的指针
};int main() {DataSource dataSource; // 创建数据源对象ReportGenerator reportGenerator(&dataSource); // 创建报告生成器,并传入数据源对象reportGenerator.GenerateReport(); // 生成报告return 0;
}
10.2.接口注入示例
代码
#include <iostream>
#include <string>// 数据源接口,定义获取数据的纯虚方法
class IDataSource {
public:virtual std::string GetData() = 0;
};// 数据源类,实现数据源接口,提供获取数据的方法
class DataSource : public IDataSource {
public:std::string GetData() override {return "Data from the data source.";}
};// 报告生成器类,依赖于数据源接口
class ReportGenerator {
public:// 构造函数,接收一个数据源接口的指针作为依赖ReportGenerator(IDataSource* dataSource) : dataSource_(dataSource) {}// 生成报告的方法void GenerateReport() {// 使用数据源接口获取数据std::string data = dataSource_->GetData();std::cout << "Generating report with data: " << data << std::endl;}private:IDataSource* dataSource_; // 数据源接口的指针
};int main() {DataSource dataSource; // 创建数据源对象ReportGenerator reportGenerator(&dataSource); // 创建报告生成器,并传入数据源对象reportGenerator.GenerateReport(); // 生成报告return 0;
}
11.附加知识:SOLID设计原则
SOLID是一组五个面向对象编程和设计的原则,旨在帮助开发者创建更加可维护、灵活和可扩展的软件。这些原则是:
-
单一职责原则(Single Responsibility Principle,SRP):
每个类应该有且仅有一个引起变化的原因,即一个类应该只负责一项职责。这有助于将类的职责分离,使代码更加模块化,提高可维护性和可测试性。 -
开放封闭原则(Open/Closed Principle,OCP):
软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着在不修改现有代码的情况下,可以通过添加新代码来扩展功能。这有助于减少影响已有功能的风险。 -
里氏替换原则(Liskov Substitution Principle,LSP):
子类必须能够替换其基类,而不影响程序的正确性。这意味着子类应该能够保持基类的行为,并且不应该破坏基类的约定。 -
接口隔离原则(Interface Segregation Principle,ISP):
不应该强迫客户端(使用接口的类)依赖于它们不需要的接口。这个原则鼓励将大型接口拆分成更小、更具体的接口,以便客户端只需实现它们所需的部分。 -
依赖倒置原则(Dependency Inversion Principle,DIP):
高层模块不应该依赖于低层模块,两者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。这个原则强调通过依赖于抽象来实现解耦和灵活性。
这些原则共同构成了SOLID原则,它们的目标是指导开发者编写更加灵活、可扩展和易于维护的代码。这些原则并不是僵硬的规则,而是一种指导思想,根据实际情况和项目需求进行适当的应用和权衡。
12.附加知识:依赖倒置原则
依赖倒置原则(Dependency Inversion Principle,DIP)是SOLID设计原则中的一部分,提出了一种关于如何设计和组织软件架构的指导思想。DIP的核心思想是:
- 高层模块不应该依赖于低层模块。两者都应该依赖于抽象。
- 抽象不应该依赖于细节。细节应该依赖于抽象。
这个原则强调了以下几个关键概念:
-
高层模块:指的是较高层次的组件、模块或类,它们通常是实现业务逻辑的部分。
-
低层模块:指的是较低层次的组件、模块或类,它们通常是实现底层细节的部分,比如工具类、数据库访问等。
-
抽象:指的是接口、抽象类或其他形式的抽象层,用于定义高层和低层之间的通信接口。
-
细节:指的是具体的实现细节,通常包括具体类、方法等。
依赖倒置原则的目标是减少组件之间的紧耦合,提高系统的灵活性、可维护性和可扩展性。通过将高层模块和低层模块都依赖于抽象,可以实现以下几个好处:
-
可替换性:高层模块可以轻松地切换不同的低层实现,而不需要修改高层代码。
-
可测试性:通过依赖于抽象,可以更容易地进行单元测试,以及在测试中使用模拟对象或桩对象。
-
模块解耦:高层模块和低层模块之间的关系由抽象定义,减少了紧密的依赖关系。
-
灵活性:系统更容易适应变化,因为只需要修改抽象或新的低层实现,而不需要修改高层模块。
在之前提供的示例中,使用接口注入的方式就体现了依赖倒置原则。通过依赖于抽象的接口(或者基类),高层模块和低层模块之间的关系由抽象定义,达到了解耦和灵活性的目标。
13.一个图形绘制应用程序。我们将创建一个图形类(Shape),并通过依赖注入来注入不同的绘制器(Drawer)来绘制不同的图形。
代码
#include <iostream>
#include <string>// 抽象绘制器接口
class Drawer {
public:virtual void Draw(const std::string& shapeType) = 0;
};// 具体的绘制器实现
class ConsoleDrawer : public Drawer {
public:void Draw(const std::string& shapeType) override {std::cout << "Drawing " << shapeType << " on console." << std::endl;}
};class FileDrawer : public Drawer {
public:void Draw(const std::string& shapeType) override {std::cout << "Drawing " << shapeType << " in file." << std::endl;}
};// 图形类,依赖于绘制器接口
class Shape {
public:Shape(Drawer* drawer) : drawer_(drawer) {}void Draw(const std::string& shapeType) {drawer_->Draw(shapeType);}private:Drawer* drawer_;
};int main() {ConsoleDrawer consoleDrawer;FileDrawer fileDrawer;Shape circle(&consoleDrawer);Shape rectangle(&fileDrawer);circle.Draw("circle");rectangle.Draw("rectangle");return 0;
}
相关文章:
![](https://img-blog.csdnimg.cn/3462d60bf6a7460a9d989299d84eb707.png)
C++笔记之设计模式:setter函数、依赖注入
C笔记之设计模式:setter函数、依赖注入 参考笔记: 1.C笔记之静态成员函数可以在类外部访问私有构造函数吗? 2.C笔记之设计模式:setter函数、依赖注入 3.C笔记之两个类的实例之间传递参数——通过构造函数传递类对象的方法详细探究…...
![](https://img-blog.csdnimg.cn/2cca6a00d5e048d0a54b372fcef8f850.png)
Spring MVC详解
文章目录 一、SpringMVC1.1 引言1.2 MVC架构1.2.1 概念1.2.2 好处 二、开发流程2.1 导入依赖2.2 配置核心(前端)控制器2.3 后端控制器2.4 配置文件2.5 访问 三、接收请求参数3.1 基本类型参数3.2 实体收参【重点】3.3 数组收参3.4 集合收参 【了解】3.5 路径参数3.6 中文乱码 四…...
![](https://www.ngui.cc/images/no-images.jpg)
谷歌公开.zip域名,应采取哪些措施应对可能的安全风险?
近期,谷歌发布了几个新的顶级域名,这些新域名包括.dad、.esq、.prof、.phd、.nexus、.foo、.mov以及本文我们将要提到的.zip域名。自发布以来,多个安全社区都开始讨论这些顶级域名所带来的影响,主要原因是.zip很容易被误认为是文件…...
![](https://www.ngui.cc/images/no-images.jpg)
css3滤镜属性filter让网页变黑白
今天是特殊的日子,抗击疫情全国哀悼日,向英雄们致敬,一路走好!应该发现了今天很多网站页面都是黑白色的,我的博客今天都是黑白色,用css3滤镜属性filter让网页马上变黑白,一行代码就搞定。 在你…...
![](https://www.ngui.cc/images/no-images.jpg)
C++教程 - How to C++系列专栏第5篇
关于专栏 这个专栏是优质的C教程专栏,如果你还没看过第0篇,点击这里去第0篇 本专栏一致使用操作系统:macOS Ventura,代码编辑器:CLion,C编译器:Clang 感谢一路相伴的朋友们,感谢你…...
![](https://img-blog.csdnimg.cn/5bff9109aa654f2aa0cc2fa8c1fe64b6.png)
Vue2向Vue3过度核心技术插槽
目录 1 插槽-默认插槽1.作用2.需求3.问题4.插槽的基本语法5.代码示例6.总结 2 插槽-后备内容(默认值)1.问题2.插槽的后备内容3.语法4.效果5.代码示例 3 插槽-具名插槽1.需求2.具名插槽语法3.v-slot的简写4.总结 4 作用域插槽1.插槽分类2.作用3.场景4.使用…...
![](https://www.ngui.cc/images/no-images.jpg)
vite配置electron、ElementPlus或者AntDesignVue
这是全部的配置原文: import { defineConfig } from vite; import vue from vitejs/plugin-vue; import electron from "vite-plugin-electron"; import electronRenderer from "vite-plugin-electron-renderer"; import polyfillExports from…...
![](https://img-blog.csdnimg.cn/92f6ee1a5ec64bddaa6c700f6dc4d207.png)
时序分解 | MATLAB实现基于SVD奇异值分解的信号分解分量可视化
时序分解 | MATLAB实现基于SVD奇异值分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于SVD奇异值分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 SVD分解重构算法,MATLAB程序,奇异值分解 (Singular Value Decompo…...
![](https://www.ngui.cc/images/no-images.jpg)
强化学习系列--时序差分学习方法(SARSA算法)
强化学习系列--时序差分学习方法(SARSA算法) 介绍示例代码 介绍 SARSA(State-Action-Reward-State-Action)是一种强化学习算法,用于解决马尔可夫决策过程(MDP)中的问题。SARSA算法属于基于值的…...
![](https://img-blog.csdnimg.cn/img_convert/acf9630ade0ea4384fef4b3d42da0408.jpeg)
深度学习9:简单理解生成对抗网络原理
目录 生成算法 生成对抗网络(GAN) “生成”部分 “对抗性”部分 GAN如何运作? 培训GAN的技巧? GAN代码示例 如何改善GAN? 结论 生成算法 您可以将生成算法分组到三个桶中的一个: 鉴于标签&#…...
![](https://img-blog.csdnimg.cn/7f5a98e09e7f4239b48a3dc7c1796349.png)
adb shell setprop 、开发者选项
App性能调试详解 Android App性能监控工具 更多系统属性参考 一、开启 GPU Render 的profiling bar: Gpu渲染速度 adb shell setprop debug.hwui.profile true adb shell setprop debug.hwui.profile visual_bars adb shell setprop debug.hwui.profile visual…...
![](https://img-blog.csdnimg.cn/0a7827fcd03043d1a7efd8ee2f025dbf.png)
性能测试面试问题,一周拿3个offer不嫌多
性能测试的三个核心原理是什么? 1.基于协议。性能测试的对象是网络分布式架构的软件,而网络分布式架构的核心是网络协议 2.多线程。人的大脑是单线程的,电脑的cpu是多线程的。性能测试就是利用多线程的技术模拟多用户去负载 3.模拟真实场景。…...
![](https://www.ngui.cc/images/no-images.jpg)
Android Bitmap压缩
Android View截屏长图拼接(RecyclerView) 我们在实际使用中,往往图片转化成Bitmap,对Bitmap操作的时候(如:截屏分享等),可能Bitmap会过大,导致无视实现对应功能。那么我们就需要对B…...
![](https://img-blog.csdnimg.cn/3e17a06eccd04e4a9bed3effa7c67dbc.png)
不同子网络中的通信过程
从输入www.baidu.com经历了什么 一、DNS(网址->IP) 二、ARP(IP->MAC) A->B:有数据发送,数据封装ip之后发现没有主机B的mac地址。然后ARP在本网段广播:检查目标地址和源地址是否在同一…...
![](https://img-blog.csdnimg.cn/img_convert/ca540cf05a785413bd60ed0005553dcc.jpeg)
Ubuntu Touch OTA-2 推出,支持 Fairphone 3 和 F(x)tec Pro1 X
导读UBports 基金会近日宣布为基于 Ubuntu 20.04 LTS (Focal Fossa) 的 Ubuntu Touch 移动操作系统发布并全面提供 OTA-2 软件更新。 Ubuntu Touch OTA-2 在首次 OTA 更新整整四个月后发布,支持新设备,包括 Fairphone 3、F(x)tec Pro1 X 和 Vollaphone X…...
![](https://img-blog.csdnimg.cn/2741bf564ac54f3b95d2a118c0b54d47.png)
【网络】数据链路层——MAC帧协议 | ARP协议
🐱作者:一只大喵咪1201 🐱专栏:《网络》 🔥格言:你只管努力,剩下的交给时间! 来到数据链路层后,完整的数据被叫做数据帧,习惯上称之为MAC帧。 MAC帧协议 | A…...
![](https://www.ngui.cc/images/no-images.jpg)
【Spring Boot】Spring Boot自动加载机制:简化应用程序的启动
在微服务盛行的今天,快速搭建和启动应用程序变得至关重要。Spring Boot作为Java生态系统中主流的框架,其自动加载机制使得开发者能够快速构建和启动应用程序。本文将详细介绍Spring Boot的自动加载机制,并通过代码示例加以说明。 首先&#…...
![](https://img-blog.csdnimg.cn/img_convert/ef1ffba49554d2c9d0f89aa6f804b908.png)
centos7搭建apache作为文件站后,其他人无法访问解决办法
在公司内网的一个虚拟机上搭建了httpsd服务,准备作为内部小伙伴们的文件站,但是搭建好之后发现别的小伙伴是无法访问我机器的。 于是寻找一下原因,排查步骤如下: 1.netstat -lnp 和 ps aux 先看下端口和 服务情况 发现均正常 2.…...
![](https://img-blog.csdnimg.cn/dd1b02bf3d2b43159cf8470574dbe3f6.png)
【开个空调】语音识别+红外发射
废话少说,直接上空调板子:YAPOF3。红外接收发射模块用的某宝上发现的YF-33(遗憾解码还没搞清楚,不然做个lirc.conf功能才多)。最后是语音识别用的幻尔的,某宝自然也有,它是个i2c的接口。 本篇胡说八道其实纯粹为了留个…...
![](https://www.ngui.cc/images/no-images.jpg)
【hibernate validator】(二)声明和验证Bean约束
首发博客地址 https://blog.zysicyj.top/ 一、声明bean约束 1. 字段级别约束 不支持静态类型字段 验证引擎直接访问实例变量,不会调用属性的访问器 在验证字节码增强的对象时,应适用属性级别约束,因为字节码增库无法通过反射确定字段访问 pac…...
![](https://www.ngui.cc/images/no-images.jpg)
Redis持久化机制之RDB,AOF与混合AOF
Redis是一款高性能的NoSQL数据库,它的速度非常快,同时也支持多种持久化机制,其中最常用的是RDB和AOF,还有一种混合AOF方式。那么这些持久化机制到底是什么,有什么不同呢? RDB是Redis默认的持久化方式&…...
![](https://img-blog.csdnimg.cn/img_convert/59fa6320f0fd1f7170e9478874b4717d.png)
为啥外卖小哥宁愿600一月租电动车,也不花2、3千买一辆送外卖!背后的原因......
大家好!我是菜哥! 又到周末了,我们聊点非技术的东西。最近知乎“为何那些穿梭于城市大街小巷的外卖小哥,宁愿每月掏出600块租一辆电动车,也不愿意掏出2、3千买一辆呢?” 冲上热榜! 听起来有点“…...
![](https://img-blog.csdnimg.cn/615ba319310d4e428c5d2aa6f1bbcf84.png)
分布式定时任务框架Quartz总结和实践(2)—持久化到Mysql数据库
本文主要介绍分布式定时任务框架Quartz集成SpringBoot持久化数据到Mysql数据库的操作,上一篇文章使用Quartz创建定时任务都是保存在内存中,如果服务重启定时任务就会失效,所以Quartz官方也提供将定时任务等信息持久化到Mysql数据库的功能&…...
![](https://www.ngui.cc/images/no-images.jpg)
Linux 服务器搭建配置,开发效率一飞冲天 - Centos 篇
大家好,我是比特桃。最近白嫖了一台 Centos 云服务器,用来做日常开发,特此记录一下搭建配置的过程。 我之前有篇文章是基于 Ubuntu 的:Linux 服务器搭建配置,开发效率一飞冲天 - Ubuntu 篇 如同个人电脑一样࿰…...
![](https://img-blog.csdnimg.cn/img_convert/dcd699a72cf280ecbbefc185b85216a1.jpeg)
Day46|leetcode 139.单词拆分
leetcode 139.单词拆分 题目链接:139. 单词拆分 - 力扣(LeetCode) 视频链接:动态规划之完全背包,你的背包如何装满?| LeetCode:139.单词拆分_哔哩哔哩_bilibili 题目概述 给你一个字符串 s 和一…...
![](https://www.ngui.cc/images/no-images.jpg)
深入理解高并发编程 - Thread 类的 stop () 和 interrupt ()
stop() stop() 方法被用于停止线程。然而,需要注意的是,stop() 方法已经被标记为已废弃(deprecated),并且不推荐使用。这是因为使用该方法可能导致不可预料的问题和数据不一致性,因此它被认为是不安全的。…...
![](https://img-blog.csdnimg.cn/86e27eb4a569461e94fc5f8e987a6e74.png)
C语言之三子棋游戏实现篇
目录 主函数test.c 菜单函数 选择实现 游戏函数 (函数调用) 打印棋盘数据 打印展示棋盘 玩家下棋 电脑下棋 判断输赢 循环 test.c总代码 头文件&函数声明game.h 头文件的包含 游戏符号声明 游戏函数声明 game.h总代码 游戏函数ga…...
![](https://img-blog.csdnimg.cn/8d20b6da88784b28b00f5fc8b1c17c03.png)
jupyter notebook 插件nbextensions的安装
安装步骤: 1、打开 jupyter notebook,新建一个 python 文件; 2、 分别输入以下代码,然后运行,出现 warning 不影响使用,如果出现 errors,则说明下载有问题: !python -m pip install…...
![](https://img-blog.csdnimg.cn/a95ffd1345154d7aabf4b602f921af81.jpeg)
Spring boot 集成单元测试
1.引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency> 2. 3.编写测试类 package com.enterprise;import com.enterpr…...
![](https://img-blog.csdnimg.cn/91bb406d6c934f03b15aed4f013f37d0.png)
基于C++的QT实现贪吃蛇小游戏
文章目录: 一:效果演示 二:实现思路 三:代码实现 widget.h widget.cpp main.cpp 一:效果演示 效果图◕‿◕✌✌✌ 代码下载 二:实现思路 通过按键控制蛇的移动,每吃一个商品蛇身就会加长…...
![](/images/no-images.jpg)
大型网站开发实例/新闻热搜榜 今日热点
Linux最大线程数及最大进程数 分类: linux2011-08-04 21:40 13924人阅读 评论(0) 收藏 举报linuxcentosthreadnullfreebsdreport查看最大线程数: cat /proc/sys/kernel/threads-max ulimit User limits - limit the use of system-wide resources. Syn…...
![](/images/no-images.jpg)
教育校园网站建设方案/推广效果最好的平台
做软件到一定层次了,就要考虑到设计了,设计了很久,就是不系统,系统的设计需要一个记录,记录就用文档,那么对项目所有包括技术上的设计都记录下来,我们就可以理解为软件的概要设计了。 在需求明确…...
网站开发需要的技术人员有什么软件/seo是什么公司
1、JAVA中线程的状态 1-1、#对象锁 在JAVA中每一个对象都有一把‘锁’,这个‘锁’可以是开放状态;也可以由某一个线程(或者多个线程)持有‘钥匙’;一旦在系统中某个对象的‘锁’存在至少一把‘钥匙’,那么任…...
![](https://img-blog.csdnimg.cn/img_convert/3aa9e6a7517a8d42f9bf53b3f261b30d.png)
wordpress 载入慢/郑州新闻发布
目录1. randsrc 无参数随机输出-1或1。有参数,按照概率输出m*m或m*n阶矩阵2. rand 随机产生0—1中某一数3. randint 无参数随机输出0或1。有参数,按照概率输出m*m或m*n阶矩阵4. randperm 返回从1到n随机分布的整数序列,长度为…...
![](/images/no-images.jpg)
dede企业网站源码/百度搜索引擎优化相关性评价
MySQL提供了大量丰富的系统函数,它们功能强大、方便易用。使用这些函数,可以极大提高用户对数据库的高效管理,更加灵活的满足不同用户的需求。从功能上可以分为以下几类函数:字符串函数、数学函数、日期和时间函数、条件判断函数、…...
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
广州白云区疫情实时报告数据/佛山快速排名seo
要做个BS的网站项目,恶补一下CSS。 CSS常用属性: 字体属性:(font)大小 font-size: x-large;(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX、PD样式 font-style: oblique;(偏斜体) itali…...