C++软件设计模式之享元模式(FlyWeight)

享元(Flyweight)模式的动机与意图

动机

享元模式的主要动机是通过共享对象来减少内存使用,从而提高系统的性能。在某些情况下,系统中可能有大量细粒度的对象,这些对象具有共同的部分状态,而这些状态可以共享。如果不进行共享,大量对象会占用大量的内存资源,特别是在对象的数量非常大的时候。享元模式通过共享这些对象的共有部分状态,使得系统只需要保存一份共有的状态,从而显著减少内存占用。

意图

享元模式的意图是通过共享技术来减少内存使用,并提高对象的创建和管理效率。具体来说,享元模式将一个对象的内部状态(可以共享的)和外部状态(不能共享的)分开,使得一个对象可以被多次共享,而每次使用时只需传递外部状态给对象。

适用场合

享元模式适用于以下场合:

  1. 对象数量庞大

    • 当一个应用程序中需要创建大量的对象,而这些对象占用大量内存时,可以考虑使用享元模式。通过共享这些对象的共有部分状态,可以显著减少内存占用。
  2. 对象状态可以分离

    • 对象的状态可以被分为内部状态和外部状态,其中内部状态是可以共享的,而外部状态是随上下文变化的。享元模式通过共享内部状态,同时在使用时传递外部状态,来实现对象的高效管理。
  3. 对象的大多数状态可以被外部化

    • 如果一个对象的大多数状态可以被外部化(即不保存在对象内部),并且这些状态可以在使用对象时传入,那么这个对象就适合使用享元模式。
  4. 需要缓存对象

    • 当需要缓存对象以提高访问效率时,可以通过享元模式来实现对象的共享和缓存,从而提高系统的性能。

具体示例

假设我们正在开发一个文本编辑器,需要在文档中显示大量的字符。每个字符对象都包含字体、颜色、大小等属性,如果不进行共享,每个字符的这些属性将占用大量的内存。通过享元模式,我们可以共享字符的字体、颜色和大小等共有部分状态,而每个字符的外部状态(如位置)则在使用时传递给对象。

字符类(内部状态)
#include <iostream>
#include <map>
#include <string>class Character {
private:char _value;
public:Character(char value) : _value(value) {}void display(const std::string& font, const std::string& color, int size) {std::cout << "显示字符: " << _value << ",字体: " << font << ",颜色: " << color << ",大小: " << size << std::endl;}
};class CharacterFactory {
private:std::map<char, std::shared_ptr<Character>> _characters;
public:std::shared_ptr<Character> getCharacter(char value) {if (_characters.find(value) == _characters.end()) {std::shared_ptr<Character> newChar = std::make_shared<Character>(value);_characters[value] = newChar;return newChar;} else {return _characters[value];}}
};

文档类(外部状态)
class Document {
private:std::vector<std::shared_ptr<Character>> _characters;std::string _font;std::string _color;int _size;
public:Document(const std::string& font, const std::string& color, int size) : _font(font), _color(color), _size(size) {}void addCharacter(char value, CharacterFactory& factory) {std::shared_ptr<Character> character = factory.getCharacter(value);_characters.push_back(character);}void display() {for (auto& character : _characters) {character->display(_font, _color, _size);}}
};

客户端代码
int main() {CharacterFactory factory;Document doc1("Arial", "Red", 12);doc1.addCharacter('A', factory);doc1.addCharacter('B', factory);doc1.addCharacter('C', factory);Document doc2("Times New Roman", "Blue", 14);doc2.addCharacter('A', factory);doc2.addCharacter('B', factory);doc2.addCharacter('D', factory);doc1.display();doc2.display();return 0;
}

代码解释

  1. Character 类

    • 代表一个字符对象,包含字符的值 _value
    • display 方法用于显示字符,同时接受字体、颜色和大小等外部状态作为参数。
  2. CharacterFactory 类

    • 用于创建和管理字符对象的工厂类。
    • 通过 getCharacter 方法,工厂类可以返回一个已存在的字符对象(共享对象),或者创建一个新的字符对象并加入到缓存中。
  3. Document 类

    • 代表一个文档,包含字符的集合 _characters 以及字体、颜色和大小等外部状态。
    • addCharacter 方法用于向文档中添加字符,通过 CharacterFactory 获取字符对象。
    • display 方法用于显示文档中的所有字符,同时传递字体、颜色和大小等外部状态给字符对象。
  4. 客户端代码

    • 创建 CharacterFactory 对象。
    • 创建两个文档对象 doc1 和 doc2,并分别为它们添加字符。
    • 显示两个文档中的字符,每个字符对象的内部状态(值)是共享的,而外部状态(字体、颜色、大小)是在使用时传递的。

总结

享元模式的主要动机是通过共享对象来减少内存使用,提高系统的性能。其适用场合包括:

  • 对象数量庞大:系统中存在大量细粒度的对象,这些对象占用大量内存。
  • 对象状态可以分离:对象的状态可以被分为内部状态和外部状态,其中内部状态是可以共享的。
  • 对象的大多数状态可以被外部化:对象的大多数状态可以不在对象内部保存,而是在使用对象时传入。
  • 需要缓存对象:通过缓存对象来提高访问效率。

通过享元模式,可以有效地管理和共享对象的共有状态,从而减少内存占用,提高系统性能。希望这些解释能帮助你更好地理解享元模式的动机、意图及其适用场合。

享元模式的 UML 类图

享元模式的 UML 类图如下所示:

+------------------------------+          +-----------------------------+
|         FlyweightFactory     |          |        Flyweight             |
|------------------------------|          |-----------------------------|
| +getInstance(key: String):   |          | +intrinsicState: String      |
|   Flyweight                   |          | +operation(extrinsicState:  |
|                               |          |   String): void             |
| +flyweights: Map<String,       |          |                             |
|   Flyweight>                  |          +-----------------------------+
| +getInstance(key: String):     |          |          +-----------------+
|   Flyweight                    |          |          | ConcreteFlyweight |
| +addFlyweight(key: String,     |          |          |------------------|
|   flyweight: Flyweight): void  |          |          | +intrinsicState: String|
+------------------------------+          |          | +operation(extrinsicState: ||          |   String): void            |+-----------------------------+         |+---------+

UML 类图解释

  1. FlyweightFactory

    • 职责:负责创建和管理享元对象。
    • 方法
      • getInstance(key: String): Flyweight:根据给定的键返回一个享元对象。如果享元对象已经存在于缓存中,则返回缓存中的对象;否则,创建一个新的享元对象并将其加入到缓存中,然后返回。
      • addFlyweight(key: String, flyweight: Flyweight): void:将新的享元对象添加到缓存中。
    • 属性
      • flyweights: Map<String, Flyweight>:存储享元对象的缓存,键通常是一个唯一标识符,用于区分不同的享元对象。
  2. Flyweight

    • 职责:定义享元对象的接口,该接口可以接受外部状态。
    • 方法
      • operation(extrinsicState: String): void:操作方法,接受外部状态作为参数。外部状态是随上下文变化的,而内部状态是共享的。
    • 属性
      • intrinsicState: String:内部状态,是可以共享的,通常在创建时设置,并且在对象的生命周期中保持不变。
  3. ConcreteFlyweight

    • 职责:实现 Flyweight 接口,定义具体的享元对象。
    • 方法
      • operation(extrinsicState: String): void:具体的实现,使用外部状态和内部状态来完成操作。
    • 属性
      • intrinsicState: String:共享的内部状态。 

享元模式的优缺点

优点
  • 减少内存占用:通过共享对象的内部状态,减少内存使用,提高系统性能。
  • 提高创建和管理效率:享元工厂可以缓存已经创建的享元对象,减少重复创建对象的开销。
  • 模块化设计:享元模式将对象的状态分离为内部状态和外部状态,使得系统的模块化设计更加清晰。
缺点
  • 增加系统复杂性:引入享元工厂和享元对象会增加系统的复杂性,需要管理内部状态和外部状态的分离。
  • 需要外部状态的传递:每次使用享元对象时,都需要传递外部状态,这可能会增加调用的复杂性。

通过享元模式,可以有效地管理和共享对象的共有状态,从而减少内存占用,提高系统的性能。希望这些解释能帮助你更好地理解享元模式的 UML 类图及其具体实现。

享元模式在C++池化技术中的应用

享元模式在池化技术中非常有用,特别是在需要频繁创建和销毁大量相似对象的场景中。 pooling(池化技术)通过预先创建一组对象并重复使用这些对象,来减少对象创建的开销和内存的频繁分配与释放。享元模式可以进一步优化池化技术,通过共享对象的内部状态来减少内存使用。

示例:GUI资源池中的享元模式

假设我们正在开发一个GUI应用程序,需要创建大量的按钮(Button)对象。每个按钮对象都有相同的背景图片,但按钮的文本内容和位置是不同的。我们可以使用享元模式来共享按钮的背景图片,从而减少内存占用。

1. 定义享元接口
#include <iostream>
#include <string>
#include <map>
#include <memory>class ButtonFlyweight {
public:virtual void draw(const std::string& text, int x, int y) const = 0;virtual ~ButtonFlyweight() {}
};

2. 定义具体享元
class ConcreteButtonFlyweight : public ButtonFlyweight {
private:std::string _backgroundImage; // 共享的内部状态
public:ConcreteButtonFlyweight(const std::string& backgroundImage) : _backgroundImage(backgroundImage) {}void draw(const std::string& text, int x, int y) const override {std::cout << "绘制按钮: " << text << ",位置: (" << x << ", " << y << "), 背景图片: " << _backgroundImage << std::endl;}
};

3. 定义享元工厂
class ButtonFlyweightFactory {
private:std::map<std::string, std::shared_ptr<ButtonFlyweight>> _flyweights;
public:std::shared_ptr<ButtonFlyweight> getButton(const std::string& backgroundImage) {if (_flyweights.find(backgroundImage) == _flyweights.end()) {std::shared_ptr<ButtonFlyweight> newButton = std::make_shared<ConcreteButtonFlyweight>(backgroundImage);_flyweights[backgroundImage] = newButton;}return _flyweights[backgroundImage];}
};

4. 定义GUI组件(使用享元)
class GUIComponent {
private:std::shared_ptr<ButtonFlyweight> _button;std::string _text;int _x;int _y;
public:GUIComponent(const std::string& text, int x, int y, ButtonFlyweightFactory& factory, const std::string& backgroundImage) :_text(text), _x(x), _y(y), _button(factory.getButton(backgroundImage)) {}void draw() const {_button->draw(_text, _x, _y);}
};

5. 客户端代码
int main() {ButtonFlyweightFactory buttonFactory;GUIComponent button1("Button 1", 10, 20, buttonFactory, "bg1.png");GUIComponent button2("Button 2", 30, 40, buttonFactory, "bg1.png");GUIComponent button3("Button 3", 50, 60, buttonFactory, "bg2.png");button1.draw();button2.draw();button3.draw();return 0;
}

代码解释

  1. ButtonFlyweight 接口

    • 定义了 draw 方法,该方法接受按钮的文本内容和位置(外部状态)作为参数。
  2. ConcreteButtonFlyweight 类

    • 实现了 ButtonFlyweight 接口,具体的 draw 方法使用传递进来的外部状态(按钮的文本内容和位置)和内部状态(背景图片)来绘制按钮。
  3. ButtonFlyweightFactory 类

    • 负责创建和管理 ButtonFlyweight 对象。
    • getButton 方法根据给定的背景图片返回一个享元对象。如果享元对象已经存在于缓存中,则返回缓存中的对象;否则,创建一个新的享元对象并将其加入到缓存中,然后返回。
    • _flyweights 属性是一个 map,用于存储享元对象,键是背景图片的路径。
  4. GUIComponent 类

    • 代表一个GUI组件,包含按钮的文本内容、位置等外部状态。
    • GUIComponent 构造函数接受按钮的文本内容、位置、享元工厂和背景图片路径作为参数,通过享元工厂获取享元对象。
    • draw 方法用于绘制按钮,调用享元对象的 draw 方法,传递按钮的文本内容和位置作为外部状态。
  5. 客户端代码

    • 创建 ButtonFlyweightFactory 对象。
    • 创建多个 GUIComponent 对象,每个对象使用相同的背景图片时,享元工厂会返回同一个享元对象。
    • 调用 draw 方法绘制按钮,每个按钮对象的内部状态(背景图片)是共享的,而外部状态(文本内容和位置)是在使用时传递的。

享元模式在GUI资源池中的优势

  1. 减少内存占用

    • 通过共享按钮的背景图片,可以显著减少内存使用。如果每个按钮都具有相同的背景图片,但不共享,那么每个按钮都会占用额外的内存来存储背景图片数据。
  2. 提高创建和管理效率

    • 享元工厂可以缓存已经创建的享元对象,减少重复创建对象的开销。这对于频繁创建和销毁按钮对象的场景非常有用。
  3. 模块化设计

    • 将按钮的内部状态(背景图片)和外部状态(文本内容和位置)分离,使得系统的模块化设计更加清晰。这有助于提高代码的可维护性和可扩展性。

进一步优化

在实际应用中,可以进一步优化享元模式,例如:

  • 使用智能指针:使用 std::shared_ptr 来管理享元对象的生命周期,确保对象在不再需要时被自动释放。
  • 多线程安全:如果应用是多线程的,可以在享元工厂中使用互斥锁(std::mutex)来确保线程安全。
  • 外部状态的封装:将外部状态封装在一个结构体或类中,然后传递给享元对象,以提高代码的可读性和可维护性。

通过这些优化,可以进一步提高享元模式在池化技术中的应用效果。希望这些解释和示例代码能帮助你更好地理解享元模式在C++池化技术中的应用。

 

结合 Composite 模式和 Flyweight 模式实现文档编辑器中的文本分层结构

在文档编辑器中,文本通常可以有层次结构,比如段落、行和字符等。我们可以使用 Composite 模式 来管理这种层次结构,而 Flyweight 模式 可以用来共享文本样式的内部状态,从而减少内存占用。为了进一步优化,我们还可以使用 有向无环图(DAG) 来实现 Flyweight 模式,使得多个对象可以共享复杂的内部状态。

示例代码

1. 定义享元接口
#include <iostream>
#include <string>
#include <map>
#include <memory>
#include <vector>class TextStyle {
public:virtual void render(char character) const = 0;virtual ~TextStyle() {}
};

2. 定义具体享元
class ConcreteTextStyle : public TextStyle {
private:std::string _font;std::string _color;int _size;
public:ConcreteTextStyle(const std::string& font, const std::string& color, int size) : _font(font), _color(color), _size(size) {}void render(char character) const override {std::cout << "绘制字符: " << character << ",字体: " << _font << ",颜色: " << _color << ",大小: " << _size << std::endl;}
};

3. 定义享元工厂
class TextStyleFactory {
private:std::map<std::string, std::shared_ptr<TextStyle>> _styles;
public:std::shared_ptr<TextStyle> getTextStyle(const std::string& font, const std::string& color, int size) {std::string key = font + "," + color + "," + std::to_string(size);if (_styles.find(key) == _styles.end()) {std::shared_ptr<TextStyle> newStyle = std::make_shared<ConcreteTextStyle>(font, color, size);_styles[key] = newStyle;}return _styles[key];}
};

4. 定义 Composite 模式中的组件接口
class TextComponent {
public:virtual void display() const = 0;virtual ~TextComponent() {}
};

5. 定义叶子节点(字符)
class TextCharacter : public TextComponent {
private:char _character;std::shared_ptr<TextStyle> _style;
public:TextCharacter(char character, const std::shared_ptr<TextStyle>& style) : _character(character), _style(style) {}void display() const override {_style->render(_character);}
};

6. 定义组合节点(段落)
class Paragraph : public TextComponent {
private:std::vector<std::shared_ptr<TextComponent>> _children;
public:void addChild(const std::shared_ptr<TextComponent>& child) {_children.push_back(child);}void display() const override {std::cout << "段落:" << std::endl;for (const auto& child : _children) {child->display();}}
};

7. 定义组合节点(行)
class Line : public TextComponent {
private:std::vector<std::shared_ptr<TextComponent>> _children;
public:void addChild(const std::shared_ptr<TextComponent>& child) {_children.push_back(child);}void display() const override {std::cout << "行:" << std::endl;for (const auto& child : _children) {child->display();}}
};

8. 客户端代码
int main() {TextStyleFactory styleFactory;// 创建文本样式std::shared_ptr<TextStyle> style1 = styleFactory.getTextStyle("Arial", "Red", 12);std::shared_ptr<TextStyle> style2 = styleFactory.getTextStyle("Times New Roman", "Blue", 14);// 创建字符std::shared_ptr<TextComponent> charA = std::make_shared<TextCharacter>('A', style1);std::shared_ptr<TextComponent> charB = std::make_shared<TextCharacter>('B', style1);std::shared_ptr<TextComponent> charC = std::make_shared<TextCharacter>('C', style1);std::shared_ptr<TextComponent> charD = std::make_shared<TextCharacter>('D', style2);std::shared_ptr<TextComponent> charE = std::make_shared<TextCharacter>('E', style2);// 创建行std::shared_ptr<TextComponent> line1 = std::make_shared<Line>();line1->addChild(charA);line1->addChild(charB);line1->addChild(charC);std::shared_ptr<TextComponent> line2 = std::make_shared<Line>();line2->addChild(charD);line2->addChild(charE);// 创建段落std::shared_ptr<TextComponent> paragraph = std::make_shared<Paragraph>();paragraph->addChild(line1);paragraph->addChild(line2);// 显示文档paragraph->display();return 0;
}

代码解释

  1. TextStyle 接口

    • 定义了一个 render 方法,该方法接受一个字符作为参数,并负责绘制该字符时使用特定的文本样式。
  2. ConcreteTextStyle 类

    • 实现了 TextStyle 接口,具体的 render 方法使用传递进来的字符和内部状态(字体、颜色、大小)来绘制字符。
  3. TextStyleFactory 类

    • 负责创建和管理 TextStyle 对象。
    • getTextStyle 方法根据给定的字体、颜色和大小生成一个唯一的键,并根据该键返回一个享元对象。如果享元对象已经存在于缓存中,则返回缓存中的对象;否则,创建一个新的享元对象并将其加入到缓存中,然后返回。
    • _styles 属性是一个 map,用于存储享元对象,键是字体、颜色和大小的组合字符串。
  4. TextComponent 接口

    • 定义了一个 display 方法,该方法用于显示文本组件。
  5. TextCharacter 类

    • 代表文档中的单个字符,继承自 TextComponent 接口。
    • display 方法调用享元对象的 render 方法来绘制字符。
  6. Line 类

    • 代表文档中的一行,继承自 TextComponent 接口。
    • addChild 方法用于向行中添加字符或其他文本组件。
    • display 方法遍历并显示所有子组件。
  7. Paragraph 类

    • 代表文档中的段落,继承自 TextComponent 接口。
    • addChild 方法用于向段落中添加行或其他文本组件。
    • display 方法遍历并显示所有子组件。
  8. 客户端代码

    • 创建 TextStyleFactory 对象。
    • 创建多个 ConcreteTextStyle 对象,并通过享元工厂获取它们。
    • 创建多个字符对象 TextCharacter,并指定其样式。
    • 创建行对象 Line,并向其中添加字符。
    • 创建段落对象 Paragraph,并向其中添加行。
    • 调用 display 方法显示整个段落的层次结构。

享元模式结合 Composite 模式的优势

  1. 减少内存占用

    • 通过共享文本样式的内部状态(字体、颜色、大小),可以显著减少内存使用。特别是在文档中大量字符使用相同的样式时,效果尤为明显。
  2. 提高创建和管理效率

    • 享元工厂可以缓存已经创建的文本样式对象,减少重复创建对象的开销。这对于频繁应用相同样式的场景非常有用。
  3. 层次结构的管理

    • 使用 Composite 模式可以方便地管理文档的层次结构,如段落、行和字符。通过组合节点和叶子节点,可以灵活地构建复杂的文本结构。
  4. 模块化设计

    • 将文本样式的内部状态和外部状态(字符)分离,使得系统的模块化设计更加清晰。这有助于提高代码的可维护性和可扩展性。

进一步优化

在实际应用中,可以进一步优化享元模式和 Composite 模式,例如:

  • 使用智能指针:使用 std::shared_ptr 来管理享元对象和文本组件的生命周期,确保对象在不再需要时被自动释放。
  • 多线程安全:如果应用是多线程的,可以在享元工厂中使用互斥锁(std::mutex)来确保线程安全。
  • 外部状态的封装:将外部状态(如字符位置)封装在一个结构体或类中,然后传递给享元对象,以提高代码的可读性和可维护性。

通过这些优化,可以进一步提高享元模式在文档编辑器中文本样式中的应用效果。希望这些解释和示例代码能帮助你更好地理解如何结合 Composite 模式和 Flyweight 模式来实现文档编辑器中的文本分层结构。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LightGBM分类算法在医疗数据挖掘中的深度探索与应用创新(上)

一、引言 1.1 医疗数据挖掘的重要性与挑战 在当今数字化医疗时代,医疗数据呈爆炸式增长,这些数据蕴含着丰富的信息,对医疗决策具有极为重要的意义。通过对医疗数据的深入挖掘,可以发现潜在的疾病模式、治疗效果关联以及患者的健康风险因素,从而为精准医疗、个性化治疗方…

STM32串口第一次接收数据时第一个字节丢失的问题

解决方法&#xff1a;开启中断之前&#xff0c;先清除标志位【1】。 串口清除标志位&#xff1a; __HAL_UART_CLEAR_PEFLAG(&huart1); HAL_UART_Receive_IT(&huart1,&RxUart, 1); 定时器清除标志位&#xff1a; __HAL_TIM_CLEAR_FLAG(&htim3,TIM_FLAG_UPDATE);…

深度学习中的残差网络、加权残差连接(WRC)与跨阶段部分连接(CSP)详解

随着深度学习技术的不断发展&#xff0c;神经网络架构变得越来越复杂&#xff0c;而这些复杂网络在训练时常常遇到梯度消失、梯度爆炸以及计算效率低等问题。为了克服这些问题&#xff0c;研究者们提出了多种网络架构&#xff0c;包括 残差网络&#xff08;ResNet&#xff09;、…

Pytorch | 从零构建EfficientNet对CIFAR10进行分类

Pytorch | 从零构建EfficientNet对CIFAR10进行分类 CIFAR10数据集EfficientNet设计理念网络结构性能特点应用领域发展和改进 EfficientNet结构代码详解结构代码代码详解MBConv 类初始化方法前向传播 forward 方法 EfficientNet 类初始化方法前向传播 forward 方法 训练过程和测…

音视频入门基础:MPEG2-TS专题(20)——ES流简介

《T-REC-H.222.0-202106-S!!PDF-E.pdf》第27页对ES进行了定义。ES流是PES packets&#xff08;PES包&#xff09;中编码的视频、编码的音频或其他编码的比特流。一个ES流&#xff08;elementary stream&#xff09;在具有且只有一个stream_id的PES packets序列中携带&#xff1…

天水月亮圈圈:舌尖上的历史与传承

在天水甘谷县&#xff0c;有一种美食如同夜空中的明月&#xff0c;散发着独特的魅力&#xff0c;它就是有着百年历史的月亮圈圈。月亮圈圈原名甘谷酥圈圈&#xff0c;据传&#xff0c;由大像山镇蒋家庄一姓李的厨师创制而成&#xff0c;后经王明玖等厨师的光大传承&#xff0c;…

YOLOv11融合[CVPR2023]FFTformer中的FSAS模块

YOLOv11v10v8使用教程&#xff1a; YOLOv11入门到入土使用教程 YOLOv11改进汇总贴&#xff1a;YOLOv11及自研模型更新汇总 《Efficient Frequency Domain-based Transformers for High-Quality Image Deblurring》 一、 模块介绍 论文链接&#xff1a;https://arxiv.org/abs…

java如何使用poi-tl在word模板里渲染多张图片

1、poi-tl官网地址 http://deepoove.com/poi-tl/ 2、引入poi-tl的依赖 <dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.12.1</version></dependency>3、定义word模板 释义&#xf…

《信管通低代码信息管理系统开发平台》Windows环境安装说明

1 简介 《信管通低代码信息管理系统应用平台》提供多环境软件产品开发服务&#xff0c;包括单机、局域网和互联网。我们专注于适用国产硬件和操作系统应用软件开发应用。为事业单位和企业提供行业软件定制开发&#xff0c;满足其独特需求。无论是简单的应用还是复杂的系统&…

8K+Red+Raw+ProRes422分享5个影视级视频素材网站

Hello&#xff0c;大家好&#xff0c;我是后期圈&#xff01; 在视频创作中&#xff0c;电影级的视频素材能够为作品增添专业质感&#xff0c;让画面更具冲击力。无论是广告、电影短片&#xff0c;还是品牌宣传&#xff0c;高质量的视频素材都是不可或缺的资源。然而&#xff…

Git远程仓库的使用

一.远程仓库注册 1.github&#xff1a;GitHub Build and ship software on a single, collaborative platform GitHub 2.gitee&#xff1a;GitHub Build and ship software on a single, collaborative platform GitHub github需要使用魔法&#xff0c;而gitee是国内的仓…

Echarts连接数据库,实时绘制图表详解

文章目录 Echarts连接数据库&#xff0c;实时绘制图表详解一、引言二、步骤一&#xff1a;环境准备与数据库连接1、环境搭建2、数据库连接 三、步骤二&#xff1a;数据获取与处理1、查询数据库2、数据处理 四、步骤三&#xff1a;ECharts图表配置与渲染1、配置ECharts选项2、动…

【Java基础面试题038】栈和队列在Java中的区别是什么?

回答重点 栈&#xff08;Stack&#xff09;&#xff1a;遵循后进先出&#xff08;LIFO&#xff0c;Last In&#xff0c;First Out&#xff09;原则。即&#xff0c;最后插入的元素最先被移除。主要操作包括push&#xff08;入栈&#xff09;和pop&#xff08;出栈&#xff09;…

idea2024创建JavaWeb项目以及配置Tomcat详解

今天呢&#xff0c;博主的学习进度也是步入了JavaWeb&#xff0c;目前正在逐步杨帆旗航&#xff0c;迎接全新的狂潮海浪。 那么接下来就给大家出一期有关JavaWeb的配置教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正…

由于这些关键原因,我总是手边有一台虚拟机

概括 虚拟机提供了一个安全的环境来测试有风险的设置或软件,而不会影响您的主系统。设置和保存虚拟机非常简单,无需更改主要设备即可方便地访问多个操作系统。运行虚拟机可能会占用大量资源,但现代 PC 可以很好地处理它,为实验和工作流程优化提供无限的可能性。如果您喜欢使…

【FPGA】ISE13.4操作手册,新建工程示例

关注作者了解更多 我的其他CSDN专栏 求职面试 大学英语 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处…

python环境中阻止相关库的自动更新

找到conda中的Python虚拟环境位置 这里以conda中的pytorch虚拟环境为例&#xff08;Python环境位置&#xff09;&#xff0c;在.conda下的envs中进入pytorch下的conda-meta路径下 新建一个空白的pinned文档 右键点击桌面或文件资源管理器中的空白处&#xff0c;选择“新建” …

重温设计模式--外观模式

文章目录 外观模式&#xff08;Facade Pattern&#xff09;概述定义 外观模式UML图作用 外观模式的结构C 代码示例1C代码示例2总结 外观模式&#xff08;Facade Pattern&#xff09;概述 定义 外观模式是一种结构型设计模式&#xff0c;它为子系统中的一组接口提供了一个统一…

uniapp 微信小程序 页面部分截图实现

uniapp 微信小程序 页面部分截图实现 ​ 原理都是将页面元素画成canvas 然后将canvas转化为图片&#xff0c;问题是我页面里边本来就有一个canvas&#xff0c;ucharts图画的canvas我无法画出这块。 ​ 想了一晚上&#xff0c;既然canvas最后能转化为图片&#xff0c;那我直接…

Flutter 基础知识总结

1、Flutter 介绍与环境安装 为什么选择 Dart&#xff1a; 基于 JIT 快速开发周期&#xff1a;Flutter 在开发阶段采用 JIT 模式&#xff0c;避免每次改动都进行编译&#xff0c;极大的节省了开发时间基于 AOT 发布包&#xff1a;Flutter 在发布时可以通过 AOT 生成高效的 ARM…