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.pswp.cn/web/63932.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/63932.shtml
英文地址,請注明出處:http://en.pswp.cn/web/63932.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LightGBM分類算法在醫療數據挖掘中的深度探索與應用創新(上)

一、引言 1.1 醫療數據挖掘的重要性與挑戰 在當今數字化醫療時代,醫療數據呈爆炸式增長,這些數據蘊含著豐富的信息,對醫療決策具有極為重要的意義。通過對醫療數據的深入挖掘,可以發現潛在的疾病模式、治療效果關聯以及患者的健康風險因素,從而為精準醫療、個性化治療方…

|-牛式-|

題目描述 下面是一個乘法豎式&#xff0c;如果用我們給定的那幾個數字來取代 * &#xff0c;可以使式子成立的話&#xff0c;我們就叫這個式子牛式。 * * * x * * ------- * * * * * * ------- * * * * 數字只能取代 * &#xff0c;當然第一位不能為 0 。 寫一個程序找…

es 3期 第18節-分頁查詢使用避坑的一些事

#### 1.Elasticsearch是數據庫&#xff0c;不是普通的Java應用程序&#xff0c;傳統數據庫需要的硬件資源同樣需要&#xff0c;提升性能最有效的就是升級硬件。 #### 2.Elasticsearch是文檔型數據庫&#xff0c;不是關系型數據庫&#xff0c;不具備嚴格的ACID事務特性&#xff…

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 方法 訓練過程和測…

Vue 2 中實現雙擊事件的幾種方法

在 Vue 2 中處理用戶交互&#xff0c;特別是雙擊事件&#xff0c;是一個常見的需求。Vue 提供了一種簡潔的方式來綁定事件&#xff0c;包括雙擊事件。本文將介紹幾種在 Vue 2 中實現雙擊事件的方法。 1. 使用 dblclick 指令 Vue 允許你直接在模板中使用 dblclick 指令來監聽雙…

音視頻入門基礎: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、動…

MongoDB 常用操作指南(Docker 環境下)

本文詳細介紹如何在 Docker 中操作 MongoDB&#xff0c;包括如何進入命令行、進行用戶認證、查看數據庫和集合&#xff0c;以及常用的索引操作和其他高頻使用的 MongoDB 方法。小白也能輕松上手 1. 在 Docker 中進入 MongoDB 命令行 進入運行 MongoDB 容器的命令行&#xff1a;…

【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專欄 求職面試 大學英語 過程控制系統 工程測試技術 虛擬儀器技術 可編程控制器 工業現場總線 數字圖像處理 智能控制 傳感器技術 嵌入式系統 復變函數與積分變換 單片機原理 線性代數 大學物理 熱工與工程流體力學 數字信號處…