《HeadFirst设计模式》笔记(上)
设计模式的目录:
1 设计模式介绍
要不断去学习如何利用其它开发人员的智慧与经验。学习前人的正统思想。
我们认为《Head First》的读者是一位学习者。
一些Head First的学习原则:
- 使其可视化
- 将文字放在相关图形内部或附近,而不是放在底部或另一页上,这样学习者解决问题的能力可提高至两倍。
- 采用对话式和个人化的风格
- 让学习者进行更深入的思考。引起读者的好起,促进、要求并鼓励读者去解决问题、得出结论、产生新的知识。
- 吸引并保持读者的注意力
- 触动他们的情感。如果是读者关心的东西,那么读者就能够记得住。
可以用下面的方法让大脑更好地吸收知识:
- 1、慢一点,理解得越多,需要记的就越少
- 2、勤做练习,自己记笔记
- 3、阅读“There are no Dumb Questions”部分。书中这些部分绝对是核心内容。
- 4、上床睡觉前不要再看别的书,或者至少不再看其他有难度的东西
- 5、多喝水
- 6、大声说出来
- 7、听听大脑怎么说。注意一下你的大脑是不是负荷太重了,如果发现自己开始浮光掠影地翻看,或者刚看的东西就忘了,这说明该休息一会儿了。
- 8、要有点感觉。要真正融入到书中的故事里,为书里照片加上自己的说明。
- 9、设计一些东西。将学来的知识应用到新项目中,甚至重构旧项目。
我们的图表风格类似于UML——尽管我们尽力遵守UML规范,但有时会为了艺术效果而略微打破规则,这往往是出于我们自身的美学考量。
书里的实践活动不是可有可无的。
我们使用“组合”这个词是在广义的面向对象(OO)意义上,这比严格意义上的UML“组合”更加灵活。当我们说‘一个对象是由另一个对象组合而成’时,我们的意思是它们之间存在一种‘包含’(HAS-A)关系。
在面向对象(OO)系统中,类通常表示既有状态(即实例变量)又有行为(即方法)的事物。在这个特定的情况下,事物实际上就是一种行为。然而,即使是行为也可以拥有自己的状态和方法;例如,飞行行为可能包含表示飞行特性的实例变量,如每分钟翼拍次数、最大飞行高度和速度等。
第一个设计原则:
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
将一些可能需要变化之处委托给别人处理,而不是使用定义在Duck类内的呱呱叫和飞行方法。
委托具体通过动态绑定来实现。
第二个设计原则:针对接口编程,而不是针对实现编程。
第三个设计原则:多用组合,少用继承。
软件开发后相比软件开发前需要更多的时间,因为需要花许多时间在系统的维护和变化上。
定义策略模式
策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
策略模式就是前面说的这么多的结合。
设计模式为您提供了一个与其他开发人员共享的词汇表。一旦你有了词汇表,你就可以更容易地与其他开发人员交流,并激励那些不知道模式的人开始学习它们。
设计模式不会直接进入代码中,而是先进入大脑中。一旦先在脑海中装入了许多关于模式的知识,就能够开始在新设计中采用它们,并当旧代码变得十分混乱时,可用它们重做旧代码。
良好的OO设计必须具备可复用、可扩充、可维护三个特性。
2 观察者模式
观察者模式可以让你的对象知悉现况。
观察者模式是JDK中使用最多的模式之一。
定义观察者模式:类图
一对多的关系。一则是提供数据的,多则是观察者。
需要注册观察者和移除观察者可以理解,
NotifyObserver则是用于在状态改变时更新所有当前观察者。
第四个设计原则:为了交互对象之间的松耦合设计而努力。
setChanged()方法用来标记状态已经改变的事实,好让notify0bservers0)知道当它被调用时应该更新观察者。如果调用notify0bserversO之前没有先调用setChangedO,观察者就“不会”被通知。Observable 内部:
通过使用setChanged()方法则可以控制WeatherData对象通知观察者的频率。
import java.util.Observable;
import java.util.Observer;public class ForecastDisplay implements Observer, DisplayElement{private float currentPressure = 29.92f;private float lastPressure;public ForecastDisplay(Observable observable) {WeatherData weatherData = (WeatherData) observable;observable.addObserver(this);}public void update(Observable observable, Object arg) {if (observable instanceof WeatherData) {lastPressure = currentPressure;currentPressure = WeatherData.getPressure();display();}}public void display() {// 在这里显示代码}
}
观察者模式:在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。
观察者模式将固定的addObserver、deleteObserver、notifyObservers、setChange放到类里面,而update抽离出来为接口。
针对接口编程则是体现在:主题与观察者都使用接口。观察者利用主题的接口向主题注册,而主题利用观察者接口通知观察者。这样可以让两者之间运行正常,又同时具有松耦合的优点。
多用组合体现在:(GeneralDisplay有一个Observable。)观察者模式利用“组合”将许多观察者组合进主题中。对象之间的这种关系不是通过继承产生的,而是在运行时利用组合的方式而产生的。
3 装饰者模式
利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
代码应该如同晚霞中的莲花一样地关闭(免于改变),如同晨曦中的莲花一样地开放(能够扩展)。
第五个设计原则:类应该对扩展开放,对修改关闭。
对扩展开放,对修改关闭的理解:有一些OO技巧,运行系统在不修改代码的情况下进行功能扩展。例如,观察者模式可以在任何时候扩展Subject(主题),而且不需向主题中添加代码。
认识装饰者模式:我们要以饮料为主体,然后在运行时以调料来“装饰”饮料。比方说,如果顾客要摩卡和奶泡深培咖啡,要做的是:
1、拿一个深培咖啡(DarkRoast)对象
2、以摩卡(Mocha)对象装饰它
3、以奶泡(Whip)对象装饰它
4、调用cost()方法,并依赖委托(delegate)将调料的价钱加上去
一些属性:
- 装饰者和被装饰者对象有相同的超类型。
- 可以用一个或多个装饰者包装一个对象。
- 既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装)的场合,都可以用装饰过的对象代替它。
- 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。
- 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地使用你喜欢的装饰者来装饰对象。
画出来的图是这样的(简单画了两个摩卡):
# Soy和Whip的代码:
public class Soy extends CondimentDecorator {Beverage beverage;public Soy(Beverage beverage) {this.beverage = beverage;}public String getDescription() {return beverage.getDescription() + ", Soy";}public double cost() {return 0.15 + beverage.cost();}
}public class Whip extends CondimentDecorator {Beverage beverage;public Whip(Beverage beverage) {this.beverage = beverage;}public String getDescription() {return beverage.getDescription() + ", Whip";}public double cost() {return 0.15 + beverage.cost();}
}
供应咖啡:
装饰者的缺点:采用装饰者实例化组件时,将增加代码的复杂度。一旦使用了装饰器,不仅需要实例化组件,还需要用不确定数量的装饰器将其包裹。
4 工厂模式
烘烤OO的精华:这句话在比喻性地谈论将面向对象编程的原则和优点应用到某个过程或项目中,就像在烘焙中加入优质的原料一样,来提升最终产品的质量。
把这部分抽离出来,当需要比萨时,就叫比萨工厂做一个。(实际上这就叫做简单工厂模式)
如何利用比萨工厂方法订购比萨:
平行的类层级:
定义工厂方法模式
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法把类实例化推迟到子类。
第六个设计原则:要依赖于抽象,不要依赖于具体类。
(这里的“依赖于”其实就是有一个。)
这个原则提倡软件模块之间的依赖关系应该建立在抽象之上,而不是具体的实现类。这样做可以提高代码的灵活性、可维护性和可扩展性,使得系统更易于管理复杂性,并支持变更而不影响依赖它的其他模块。
应用工厂方法之后,类图看起来就像这样:
避免在OO设计中违反依赖倒置原则的指导方针:
- 变量不可以持有具体类的引用
- 不要让类派生自具体类
- 不要覆盖基类中已实现的方法
定义抽象工厂模式
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道(或关心)实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。
5 单例模式
单例模式:用来创建独一无二对象的门票,这类对象仅有一个实例。
有一些对象只需要一个,比如说:线程池(threadpool)、缓存(cache)、对话框、处理偏好设置和注册表(registry)的对象、日志对象,充当打印机、显卡等设备的驱动程序的对象。
关键:如何保证一个对象只能被实例化一次。
C++实现单例设计模式:(将构造函数定义为私有成员,然后在静态成员函数进行实例化和返回)
#include <iostream>
#include <mutex>class Singleton {
private:// 私有构造函数,防止外部创建实例Singleton() {// 可以初始化一些资源}// 删除拷贝构造函数和赋值操作符,防止复制Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;public:// 静态成员函数,作为全局访问点static Singleton* getInstance() {// 使用局部静态变量来保证线程安全(C++11及以上)static Singleton instance;return &instance;}// 示例方法void showMessage() const {std::cout << "Hello, I'm a Singleton!" << std::endl;}
};// 使用示例
int main() {// 获取单例对象Singleton* singleton = Singleton::getInstance();// 调用单例对象的方法singleton->showMessage();return 0;
}
帮Choc-O-Holic改进CholcolateBoiler类:
public class CholcolateBoiler {private boolean empty;private boolean boiled;public static CholcolateBoiler uniqueInstance;private CholcolateBoiler() {empty = true;boiled = false;}public static CholcolateBoiler getInstance() {if(uniqueInstance == null) {uniqueInstance = new CholcolateBoiler;}return uniqueInstance;}public void fill() {if(isEmpty()) {empty = false;boiled = false;}}
}
定义单例模式
单例模式确保一个类只有一个实例,并提供一个全局访问点。
能改善多线程吗?
1、如果getInstance()的性能对应用程序不是很关键,就什么都别做
如果可以接受getInstance()造成的额外负担,就不要管了。
2、改为预先创建实例,而不是延迟创建实例。
3、用“双重检查加锁”,在getInstance()中减少使用同步
利用双重检查加锁,首先检查实例是否已经创建了,如果尚未创建,才进行同步。
是否可以创建一个类,把所有的方法和变量都定义为静态的,把类直接当做一个单件?
如果类自给自足,而且不依赖于复杂的初始化,那么可以。但是,因为静态初始化的控制权是在Java手中,这么做有可能导致混乱,特别是当有许多类牵涉其中时。这么做常常会造成一些微妙的、不容易发现的和初始化的次序有关的bug。除非有绝对的必要使用类的单例,否则还是建议使用对象的单例。
6 封装调用
把封装带到一个全新的境界:把方法调用封装起来。
利用命令对象,把请求封装成一个特定对象。如果对每个按钮都存储一个命令对象,那么当按钮被按下的时候,就可以请命令对象做相关的工作。
答案是这个:
GarageDoorOpenCommand类:
public class GarageDoorOpenCommand implements Command {GarageDoor garageDoor;public class GarageDoorOpenCommand(GarageDoor garageDoor) {this.garageDoor = garageDoor;}public void execute() {garageDoor.up();}
}
定义命令模式
命令模式:将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。
写文档:
使用宏命令:
需要关闭按钮的命令,代码如下:
LightOffCommand lightOff = new LightOffCommand(light);
StereoOffCommand stereoOff = new StereoOffCommand(light);
TVOffCommand tvOff = new TVOffCommand(tv);
HottubOffCommand hottubOff = new HottubOffCommand(hottub);
public void undo() {for (int i = 0; i < commands.length; i++) {commands[i].undo();}
}
命令模式的更多用途:队列请求
命令可以将运算块打包(一个接收者和一组动作),然后将它传来传去,就像是一般的对象一样。利用这样的特性衍生一些应用,例如:日程安排、线程池、工作队列等。
你认为Web服务器如何应用这样的队列方式?还能想到任何其他的应用吗?
命令模式用于日志请求:通过新增两个方法(store()、load())来实现。
7 适配器模式与外观模式
客户使用适配器的过程如下:
1、客户通过目标接口调用适配器的方法对适配器发出请求。
2、适配器使用被适配者接口把请求转换成被适配者的一个或多个调用接口。
3、客户接收到调用的结果,但并未察觉这一切是适配器在起转换作用。
public class DuckAdapter implements Turkey {Duck duck;public DuckAdapter(Duck duck) {this.duck = duck;}public void gobble() {duck.quack();}public void fly() {duck.fly();}
}
适配器模式的工作是将一个接口转换成另一个。外观模式:让一个适配器包装多个被适配者。
定义适配器模式
适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。
类适配器通过多重继承来实现。
对象适配器利用组合的方式将请求传送给被适配器。
外观模式:例如,想要看电影,只要调用一个方法(就是watchMovie())就可以了。灯光、DVD播放器、投影机、功放、屏幕、爆米花,一口气全部搞定。
定义外观模式
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
第七个设计原则:最少知识原则:只和你的密友谈话。
如何不要赢得太多的朋友和影响太多的对象。
就任何对象而言,在该对象的方法内,我们只应该调用属于以下范围的方法:
- 该对象本身
- 被当做方法的参数而传递进来的对象
- 此方法所创建或实例化的任何对象
- 对象的任何组件
8 封装算法
模板方法模式:在一个方法中定义一个算法的股价,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
第八个设计原则:
好莱坞原则:别调用我们,我们会调用你。
我们允许底层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎样使用这些低层组件。换句话说,高层组件对待低层组件的方式是”别调用我们,我们会调用你“。
模板方法很常见的原因是因为对创建框架来说,这个模式简直棒极了。由框架控制如何做事情,而由使用这个框架的人指定框架算法中每个步骤的细节。
用模板方法排序
如果要排序鸭子,就需要实现这个compareTo()方法:
模板方法是最常用的方法。因为模板方法提供了一种基本的方法来实现代码复用,使得子类能够指定行为。
模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
9 迭代器与组合模式
错了,应该是:
一个可能的迭代器接口:
迭代器:
public class PancakeHouseIterator implements Iterator {ArrayList items;int position = 0;public PancakeHouseIterator(ArrayList items) {this.items = items;}public Object next() {MenuItem menuItem = items.get(position);position = position + 1;return menuItem;}public boolean hasNext() {if(position >= items.size() || items.get(position) == null) {return false;} else {return true;}}
}
菜单:
public class PancakeHouseMenu {ArrayList menuItems;// 构造器在这里//addItem在这里public Iterator createIterator() {rerurn new PancakeHouseIterator(menuItems);}//菜单的其他方法在这里
}
然后就可以快乐地使用迭代器进行打印了:
进一步的,将煎饼和午餐进行合并:
定义迭代器模式
迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
当我们运行一个类不但要完成自己的事情(管理某种聚合),还同时要担负更多的责任(例如遍历)时,我们就给了这个类两个变化的原因。这违反了下面的设计原则。
第九个设计原则:一个类应该只有一个引起变化的原因。
如果菜单出现了树形结构,则需要使用组合模式:
组合模式允许你将对象组合成树形结构来表现”整体/部分“层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
组合模式以单一责任设计原则换取透明性。透明性:通过允许组件接口包含子管理操作和叶节点操作,客户端可以统一地处理复合对象和叶节点;因此,一个元素是复合对象还是叶节点对于客户端来说变得透明。在该模式下,可以认为叶节点是没有孩子的节点。(事实上,代码实现上也是认为没有孩子的节点是叶节点)
组合迭代器
CompositeIterator是一个不可小觑的迭代器。它的工作是遍历组件内的菜单项,而且确保所有的子菜单都被包括进来。
下面是代码,看不懂。。。特别是hasNext函数中判断iterator.hasNext。
import java.util.*;public class CompositeIterator implements Iterator {Stack stack = new Stack(); // 使用栈来管理迭代器public CompositeIterator(Iterator iterator) {stack.push(iterator); // 将顶层组合的迭代器压入栈中}public Object next() {if (hasNext()) { // 确保还有下一个元素Iterator iterator = (Iterator) stack.peek(); // 获取当前栈顶的迭代器MenuComponent component = (MenuComponent) iterator.next(); // 获取下一个组件if (component instanceof Menu) { // 如果是菜单,继续递归stack.push(component.createIterator()); // 将子菜单的迭代器压入栈中}return component; // 返回当前组件} else {return null; // 没有下一个元素时返回null}}public boolean hasNext() {if (stack.empty()) { // 如果栈为空,表示没有下一个元素return false;} else {Iterator iterator = (Iterator) stack.peek(); // 获取当前栈顶的迭代器if (!iterator.hasNext()) { // 如果当前迭代器没有下一个元素stack.pop(); // 弹出当前迭代器return hasNext(); // 递归检查下一个迭代器} else {return true; // 当前迭代器还有下一个元素}}}public void remove() {throw new UnsupportedOperationException(); // 不支持删除操作}
}
有时候,如果一个组合结构很复杂,或者遍历的代价太高,那么实现组合节点的缓存就很有帮助。
迭代器:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
组合模式:允许你将对象组成树形结构来表现“整体/部分”的层次结构。组合能让客户以一致的方式处理和别对象和对象组合。
10 状态模式
“策略模式和状态模式是双胞胎,在出生时才分开。”
策略模式是围绕可以互换的算法来创建成功业务的。而状态模式走的是更崇高的路,它通过改变对象内部的状态来帮助对象控制自己的行为。
public class SoldOutState implements State {GumballMachine gumballMachine;public SoldOutState(GumballMachine gumballMachine) {this.gumballMachine = gumballMachine;}public void insertQuarter() {System.out.println("You can't insert a quarter, the machine is sold out");}public void ejectQuarter() {System.out.println("You can't eject, you haven't inserted a quarter yet");}public void turnCrank() {System.out.println("You turned, but there are no gumballs");}public void dispense() {System.out.println("No gumball dispensed");}
}
定义状态模式
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
状态模式的类图:
相关文章:
《HeadFirst设计模式》笔记(上)
设计模式的目录: 1 设计模式介绍 要不断去学习如何利用其它开发人员的智慧与经验。学习前人的正统思想。 我们认为《Head First》的读者是一位学习者。 一些Head First的学习原则: 使其可视化将文字放在相关图形内部或附近,而不是放在底部…...
Ubuntu更改内核
需求背景: 由于软件需要在较低版本或者指定版本才可以运行 版本: 配置文件: vi /etc/default/grub 启动界面: 可运行版本: 解决方案: 方案1、更改启动顺序 sudo vi /etc/default/grub 方案2、调整启动顺…...
广告公司咋找客户?怎么获取目标企业的采购部联系方式
在广告行业,获取目标企业采购部的联系方式是开展业务、拓展客户的关键一步。分享一些实用的方法,希望能帮到正在为获取联系方式而发愁的广告行业的朋友们。 一、利用官方网站和社交媒体平台 1. 官网 大多数企业的官方网站都会提供一些联系方式…...
个人在技术领导力方面的自我反思与提升
大家好!我是 [数擎 AI],一位热爱探索新技术的前端开发者,在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情,欢迎关注我的文章,我们一起成长、进步! 开发领域:前端开发 | A…...
鸿蒙面试 2025-01-11
ArkTs 和TS的关系? ArkTS(方舟开发语言)与 TypeScript(TS)存在紧密联系,同时也有显著区别: 联系 语法基础:ArkTS 在语法层面大量借鉴了 TypeScript ,TypeScript 里诸如…...
Vim的使用方法
Vim的使用方法 来自Linux 日常操作与基础知识 | archlinux 简明指南 终端编辑器 vim 的使用 我们需要掌握一个能在终端中进行文本编辑的软件,这里介绍 vim。 创建并编辑名为 hello.txt 的文件: vim hello.txt此时可以看到进入了一个空的界面…...
什么是卷积网络中的平移不变性?平移shft在数据增强中的意义
今天来介绍一下数据增强中的平移shft操作和卷积网络中的平移不变性。 1、什么是平移 Shift 平移是指在数据增强(data augmentation)过程中,通过对输入图像或目标进行位置偏移(平移),让目标在图像中呈现出…...
Java基础:equals()方法与==的区别
1、超类Object的equals()底层原理: 在Object超类中已经提供了equals()方法,源码如下: public boolean equals(Object obj) { return (this obj); } 所有的对象都拥有标识(内存地址)和状态(数据&a…...
备战蓝桥杯 队列和queue详解
目录 队列的概念 队列的静态实现 总代码 stl的queue 队列算法题 1.队列模板题 2.机器翻译 3.海港 双端队列 队列的概念 和栈一样,队列也是一种访问受限的线性表,它只能在表头位置删除,在表尾位置插入,队列是先进先出&…...
《分布式光纤测温:解锁楼宇安全的 “高精度密码”》
在楼宇建筑中,因其内部空间庞大,各类电器设施众多,如何以一种既高效又稳定,兼具低成本与高覆盖特性的方式,为那些关键线路节点开展温度监测,是目前在安全监测领域一项重点研究项目,而无锡布里渊…...
每日一题(一):识别字符串中的字符是否唯一
目录 一、前言 二、题目 三、题目分析 (一)明确需求 (二)分析思路 四、将思路转变为一个程序 C代码 C代码 注释: 五、总结 一、前言 作为博主在本系列文章中的第一篇文章,博主先对本系列做一个简单的介绍…...
【翻译】2025年华数杯国际赛数学建模题目+翻译pdf自取
保存至本地网盘 链接:https://pan.quark.cn/s/f82a1fa7ed87 提取码:6UUw 2025年“华数杯”国际大学生数学建模竞赛比赛时间于2025年1月11日(周六)06:00开始,至1月15日(周三)09:00结束ÿ…...
如何稳定使用 O1 / O1 Pro,让“降智”现象不再困扰?
近期,不少朋友在使用 O1 或 O1 Pro 模型时,都会碰到“降智”或“忽高忽低”的智力波动,比如无法识图、无法生成图片、甚至回答准确度也不稳定。面对这些问题,你是不是也感到头疼呢? 为了找到更可靠的解决办法…...
【Linux】4.Linux常见指令以及权限理解(2)
文章目录 3. Linux指令3.1 ls指令和rm指令补充3.2 man指令(重要)3.3cp指令(重要)输出重定向3.3.1ubuntu20.04如何安装tree 3.4 mv指令(重要)mv指令更改文件名mv指令更改目录名 如何看待指令指令的重命名3.5…...
神州数码交换机和路由器命令总结
神州数码交换机和路由器命令总结 一、神州数码交换机命令总结 1. 交换机恢复出厂设置及其基本配置. 1) //进入特权模式 2) del startup.cfg 2. Telnet方式管理交换机. 1) //进入全局配置模式 2) enable password 0 [密码] 3) Line 0 4 4) Password 0 [密码] 5) Login 3. 交换机…...
echarts: 双柱柱状图同时两侧双y轴问题
问: 现在又有一个问题:echarts双柱柱状图,同时左侧的y轴有刻度,右侧的y轴也有刻度,双y轴,y轴每一个刻度都对应虚线,这时候会有一个问题,左侧的y轴的虚线和右侧y轴的虚线没对应&…...
计算机网络八股文学习笔记
文章目录 计算机网络基础网络分层模型OSI七层模型TCP/IP四层模型 HTTP从输入URL到页面展示到底发生了什么?(非常重要)HTTP状态码HTTP Header中常见的字段有哪些?HTTP和HTTPS有什么区别?(重要)HTTP/1.0和HTTP/1.1有什么区别?HTTP/1.1和HTTP/2.0有什么区别?HTTP/2.0和HTTP/3…...
java中json字符串键值获取
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version> </dependency>使用fastjson依赖 JSONObject jsonObject JSON.parseObject(s); 这个jsonObject本质就是一个map&…...
MySQL的安装
MySQL典型的关系型数据库(RDBMS):oracle、MySQL、SqlServer MySQL的版本 5.5~5.7、8.0 MySQL的安装和配置 下载地址: https://downloads.mysql.com/archives/community/ 安装包 (x86, 64-bit), MSI Installer 执行下一步即…...
Open FPV VTX开源之第一次出图
Open FPV VTX开源之第一次出图 1. 源由2. 连线2.1 飞控2.2 调试 3. serial3.1 启动log - uboot3.2 登录版本 - linux3.3 获取有线IP 4. ssh - linux5. PixelPilot出图6. 总结7. 参考资料8. 补充 - 8812AU网卡 1. 源由 在《Open FPV VTX开源之硬件规格及组成》章节中࿰…...
R语言在森林生态研究中的魔法:结构、功能与稳定性分析——发现数据背后的生态故事!
森林生态系统结构、功能与稳定性分析与可视化研究具有多方面的重要意义,具体如下: 一、理论意义 ●深化生态学理论 通过研究森林生态系统的结构、功能与稳定性,可以深化对生态系统基本理论的理解。例如,生物多样性与生态系统稳定性…...
qt QLabel QPushButton 控件重写paintEvent后 控件消失
qt 继承自PushButton控件的类 重写paintEvent后 控件消失 解决办法,在paintevent结尾加上这条语句:QPushButton::paintEvent(event); void MyButton::paintEvent(QPaintEvent *event) {QPushButton::paintEvent(event); } 这里QPushButton不能写成Q…...
安全基础-互联网技术基础
互联网技术基础 概述:计算机网络、网络协议、HTTP协议、前端与后端技术、Web服务器、数据库以及浏览器等 目录 互联网技术基础前言一、计算机网络定义二、网络协议和协议分层1.OSI七层模型2.TCP/IP四层模型 三、HTTP协议1、HTTP协议的特点2、HTTP请求3、HTTP响应4、…...
【Rust自学】11.9. 单元测试
喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 11.9.1. 测试的分类 Rust把测试分为两类,一个是单元测试,一个是集成…...
了解Node.js
Node.js是一个基于V8引擎的JavaScript运行时环境,它允许JavaScript代码在服务器端运行,从而实现后端开发。Node.js的出现,使得前端开发人员可以利用他们已经掌握的JavaScript技能,扩展技能树并成为全栈开发人员。本文将深入浅出地…...
二十三种设计模式-原型模式
原型模式(Prototype Pattern)是一种创建型设计模式,它通过拷贝现有的实例来创建新的实例,而不是通过新建实例。这种方式可以避免复杂的构造过程,同时还能保持对象的创建和使用分离,提高系统的灵活性和扩展性…...
蓝桥与力扣刷题(66 加一)
题目: 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外,这个整数不会以零开头。 示例 1: 输入…...
Markdown 分级标题
Markdown 分级标题 1. 前言2. 语法详解2.1 SeText风格2.2 Atx风格 3. 使用场景及实例4. 小结5. 其他风格5. 其他文章快来试试吧🎈 Markdown 分级标题 👈点击这里也可查看 1. 前言 关于 Markdown 的分级标题,官方给出了如下定义: …...
回归预测 | MATLAB基于RF-Adaboost多输入单输出回归预测
回归预测 | MATLAB基于RF-Adaboost多输入单输出回归预测 目录 回归预测 | MATLAB基于RF-Adaboost多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 回归预测 | MATLAB基于RF-Adaboost多输入单输出回归预测。 1.Matlab实现RF-Adaboost随机森林集成学习…...
字符串相关类之可变字符序列:StringBuffer、StringBuilder
前言: 小编最近找了份兼职,时间比较紧张 但不影响继续日更一篇,我们继续一起进步吧!!! 我们一直都是以这样的形式,让新手小白轻松理解复杂晦涩的概念, 把Java代码拆解的清清楚楚&a…...
git提交
基本流程:新建分支 → 分支上开发(写代码) → 提交 → 合并到主分支 拉取最新代码因为当前在 master 分支下,你必须拉取最新代码,保证当前代码与线上同步(最新),执行以下命令:bashgit pull orig…...
ceph osd df 输出详解
ceph osd df 命令用于显示 Ceph 集群中各个 OSD(对象存储守护进程)的详细信息。以下是输出中各列的含义: ID:OSD 的唯一标识符。 CLASS:OSD 所属的设备类别,例如 SSD、HDD 等。 WEIGHT:OSD 的…...
Unity3D实现自定义河流路径或泥石流路径
系列文章目录 untiy工具 文章目录 系列文章目录👉前言👉一、效果如下👉二、编辑效果如下👉三、简单使用Tool👉四、实现水流从上到下流下来的效果👉壁纸分享👉总结👉前言 此工具是一个插件,插件很好用,可以根据地形编辑河流的走向以及宽度,也可以发挥想象编辑…...
【数据结构】双向链表
目录 1. 双向链表 1.1特性 1.2双向链表相关操作 1.3 双向循环链表 1. 双向链表 1.1特性 逻辑结构:线性结构 存储结构:链式存储 操作:增删改查 typedef int datatype; typedef struct node {datatype data; //数据域struct node …...
android进入fastboot
安装windows驱动。android进入fastboot模式后,需要Windows驱动来跟adb通信,所以需要预先安装Windows usb驱动,否则进入fastboot模式后,无法使用adb连接手机。 下载网址:https://developer.android.com/studio/run/win-…...
verilogHDL仿真详解
前言 Verilog HDL中提供了丰富的系统任务和系统函数,用于对仿真环境、文件操作、时间控制等进行操作。(后续会进行补充) 正文 一、verilogHDL仿真详解 timescale 1ns/1ps //时间单位为1ns,精度为1ps, //编译…...
见微知著:Tripo 开创 3D 生成新时代
关于 VAST VAST 成⽴于 2023 年 3 ⽉,是⼀家致⼒于通⽤ 3D 大模型研发的 AI 公司,公司⽬标是通过打造⼤众级别的 3D 内容创作⼯具,建⽴ 3D 的 UGC 内容平台,让基于 3D 的空间成为⽤户体验、内容表达、提升新质⽣产⼒的关键要素。 2024 年初,VAST 推出数⼗亿参数级别的 3…...
【AI自动化渗透】大模型支持的自动化渗透测试,看蚂蚁和浙大的
参考文章: https://mp.weixin.qq.com/s/WTaO54zRxtNMHaiI1tfdGw 最近,美国西北大学,浙江大学,蚂蚁集团的一些专家学者联手发表了一篇论文,介绍了一个PentestAgent的方案,实现了渗透测试自动化。 01 技术方案 图的字…...
React 中事件机制详细介绍:概念与执行流程如何更好的理解
React 的事件机制是一个非常重要的概念,它涉及到 React 如何处理用户的交互事件。React 的事件系统与传统的 DOM 事件系统有所不同,它在底层使用了事件委托和合成事件(Synthetic Events)来优化性能。下面,我们将从 Rea…...
时序数据库InfluxDB—介绍与性能测试
目录 一、简述 二、主要特点 三、基本概念 1、主要概念 2、保留策略 3、连续查询 4、存储引擎—TSM Tree 5、存储目录 四、基本操作 1、Java-API操作 五、项目中的应用 六、单节点的硬件配置 七、性能测试 1、测试环境 2、测试程序 3、写入测试 4、查询测试 一…...
解决idea中无法拖动tab标签页的问题
1、按 Ctrl Alt S 打开设置,找到路径 File | Settings | Appearance & Behavior | Appearance 2、去掉勾选 Drag-and-drop with Alt pressed only 即可...
ffplay 命令行 从视频第N帧开始读取 ffmpeg 命令行 提取第N帧图片
ffmpeg中没有直接的命令读取第N帧 但是可以通过 t N/framerate 来获取到具体第N帧的时间 然后用 -ss t进行跳转。 比如帧率(frame rate)为24fps的视频G:/1/1.mp4文件从第1000帧开始进行播放,先计算出时间为 t 41.66666 ffplay -i G:/1/1.…...
【web靶场】之upload-labs专项训练(基于BUUCTF平台)
前言 该靶场,是通过平台BUUCTF在线评测中的靶场进行的,基于linux搭建的 当然若是想要该靶场,可以采用github上的醒目,点击后面文字即可访问c0ny1/upload-labs: 一个想帮你总结所有类型的上传漏洞的靶场 或者本人分享在网盘中&a…...
HTML5 Audio(音频)
HTML5 Audio(音频) HTML5 的 <audio> 元素是一个重要的革新,它为网页开发者提供了一种简单的方式来嵌入音频内容。在这篇文章中,我们将探讨 HTML5 <audio> 元素的特性、用法、浏览器兼容性,以及如何通过 JavaScript 和 CSS 对其进行控制和定制。 1. HTML5 <…...
go语言学习
字典(映射)类型 (Map) 以键值对为元素去存储元素 Map的特点: 键不能重复。 键必须是(int,bool,float,string,array)这些可以哈希的 (如果自定义类型想要作为键,需要自…...
OpenCV相机标定与3D重建(53)解决 Perspective-3-Point (P3P) 问题函数solveP3P()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 根据 3 个 3D-2D 点对应关系找到物体的姿态。 cv::solveP3P 是 OpenCV 中的一个函数,用于解决 Perspective-3-Point (P3P) 问题。该问…...
【西北工业大学主办 | EI检索稳定 | 高H值专家与会报告】2025年航天航空工程与材料技术国际会议(AEMT 2025)
2025 年航天航空工程与材料技术国际会议(AEMT 2025)将于2025年2月28日至3月2日在中国天津召开。本届会议由西北工业大学主办,由北京航空航天大学、北京理工大学作为支持单位加入,AEIC 学术交流中心协办。 AEMT 2025 旨在汇聚来自全…...
卷积神经02-CUDA+Pytorch环境安装
卷积神经02-CUDAPytorch环境安装 在使用Python进行pytorch的使用过程中遇到各种各样的版本冲突问题,在此进行记录 0-核心知识脉络 1)根据自己电脑的CUDA版本安装对应版本的Pytorch,充分的使用GPU性能2)电脑要先安装【CUDA ToolKi…...
监听器与RBAC权限模型
目录 1、监听器ServletContextListener1.1、主要用途1.2、接口方法1.3、实现步骤1.4、示例代码1.5、使用场景 2、德鲁伊数据源2.1、主要特性2.2、配置 DruidDataSource 3、RBAC权限模型3.1、什么是RBAC3.2、RBAC 的核心概念3.3、RBAC 的优势3.4、RBAC 的实现步骤 1、监听器Serv…...
根据浏览器的不同类型动态加载不同的 CSS 文件
实现思路: 安装并引入 vue 项目相关的 CSS 文件:首先确保你有为不同浏览器准备了不同的 CSS 文件(例如,style-chrome.css,style-firefox.css,style-ie.css 等)。 在 index.js 中根据浏览器类型…...