設計模式系列(08):創建型模式 - 原型模式

系列導讀:完成創建型模式的學習,我們來看最后一個創建型模式——原型模式。它通過復制已有對象來創建新對象,是一種獨特的創建方式。

解決什么問題:通過復制現有對象來創建新對象,而不是重新實例化。適用于對象創建成本高、需要保持狀態的場景。

在實際開發中,有時候創建一個對象的成本很高,比如需要從數據庫查詢大量數據、進行復雜計算、或者建立網絡連接等。如果需要創建多個相似的對象,每次都重新執行這些操作就太浪費了。

原型模式提供了一個聰明的解決方案:先創建一個原型對象,然后通過復制這個原型來創建新對象。這樣既保留了對象的狀態,又避免了重復的創建成本。

本文在系列中的位置

  • 前置知識:建造者模式
  • 系列角色:創建型模式收尾
  • 難度等級:★★★☆☆(需要理解深拷貝和淺拷貝)
  • 后續學習:結構型模式:適配器模式

目錄

  • 1. 模式概述
  • 2. 使用場景
  • 3. 優缺點分析
  • 4. 實際應用案例
  • 5. 結構與UML類圖
  • 6. 代碼示例
  • 7. 測試用例
  • 8. 常見誤區與反例
  • 9. 最佳實踐
  • 10. 參考資料與延伸閱讀

1. 模式概述

原型模式(Prototype Pattern)是一種創建型設計模式。它通過克隆現有對象來創建新對象,而不是通過實例化類來創建。適用于對象創建成本高、狀態復雜或需批量復制的場景。

1.1 定義

用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象。

1.2 目的

  • 對象復制,提升效率
  • 避免子類膨脹,簡化擴展
  • 支持動態配置和運行時擴展

2. 使用場景

原型模式在實際開發中應用廣泛,常見場景包括:

  1. 文檔/模板復制:如Word、PPT、設計稿等模板批量生成。
  2. 游戲開發:如角色、道具、場景等對象池批量克隆。
  3. 緩存/對象池:如數據庫連接、線程、任務等對象池管理。
  4. 配置/環境克隆:如系統配置、環境參數的快速復制。

真實業務背景舉例:

  • OA系統支持一鍵復制審批單、合同、報表等,原型模式可高效實現。
  • 游戲引擎批量生成怪物、NPC、道具等,原型模式提升性能。
  • 云平臺環境模板、配置模板的快速克隆。

3. 優缺點分析

3.1 優點

  1. 性能優化:減少重復創建開銷,提升系統響應速度。
  2. 簡化擴展:無需大量子類,支持動態擴展和運行時配置。
  3. 靈活性高:可動態注冊、批量復制,適應多變需求。

3.2 缺點

  1. 深拷貝復雜:對象關系復雜時,深拷貝實現難度大。
  2. 克隆限制:如不可變對象、資源句柄等難以克隆。
  3. 維護成本:需保證克隆對象狀態一致性,易出錯。

4. 實際應用案例

  1. 文檔/模板復制:如Word、PPT、設計稿等模板批量生成。
  2. 游戲開發:如角色、道具、場景等對象池批量克隆。
  3. 緩存/對象池:如數據庫連接、線程、任務等對象池管理。
  4. 配置/環境克隆:如系統配置、環境參數的快速復制。

5. 結構與UML類圖

@startuml
package "Prototype Pattern" #DDDDDD {interface Prototype {+ clone(): Prototype}class ConcretePrototype implements Prototype {- field: String+ clone(): Prototype}class PrototypeRegistry {+ addPrototype(key: String, prototype: Prototype): void+ getPrototype(key: String): Prototype- prototypes: Map<String, Prototype>}Prototype <|.. ConcretePrototypePrototypeRegistry o-- Prototype : prototypes
}
@enduml

6. 代碼示例

6.1 基本結構示例

業務背景: 實現原型模式的基本結構,支持對象克隆和注冊表管理。

package com.example.patterns.prototype;import java.util.HashMap;
import java.util.Map;
import java.util.Objects;// 原型接口,定義克隆方法
public interface Prototype {/*** 克隆當前對象* @return 克隆后的新對象*/Prototype clone();
}// 具體原型實現,支持基本屬性克隆
public class ConcretePrototype implements Prototype {private String field;private int value;public ConcretePrototype(String field, int value) { this.field = field;this.value = value;}// 拷貝構造函數,用于克隆private ConcretePrototype(ConcretePrototype other) {this.field = other.field;this.value = other.value;}@Overridepublic Prototype clone() { return new ConcretePrototype(this); }// Getter和Setter方法public String getField() { return field; }public void setField(String field) { this.field = field; }public int getValue() { return value; }public void setValue(int value) { this.value = value; }@Overridepublic String toString() {return "ConcretePrototype{field='" + field + "', value=" + value + "}";}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;ConcretePrototype that = (ConcretePrototype) o;return value == that.value && Objects.equals(field, that.field);}@Overridepublic int hashCode() {return Objects.hash(field, value);}
}// 原型注冊表,管理原型對象
public class PrototypeRegistry {private static final Map<String, Prototype> prototypes = new HashMap<>();/*** 注冊原型對象*/public static void addPrototype(String key, Prototype prototype) {if (key == null || prototype == null) {throw new IllegalArgumentException("Key and prototype cannot be null");}prototypes.put(key, prototype);}/*** 獲取原型的克隆對象*/public static Prototype getPrototype(String key) {Prototype prototype = prototypes.get(key);if (prototype == null) {throw new IllegalArgumentException("Prototype not found for key: " + key);}return prototype.clone();}/*** 移除原型*/public static void removePrototype(String key) {prototypes.remove(key);}/*** 清空所有原型*/public static void clear() {prototypes.clear();}
}

6.2 深拷貝實現示例

業務背景: 實現包含復雜對象的深拷貝,避免引用共享問題。

// 復雜對象示例:員工信息包含地址對象
public class Address implements Cloneable {private String city;private String street;private String zipCode;public Address(String city, String street, String zipCode) {this.city = city;this.street = street;this.zipCode = zipCode;}// 深拷貝實現@Overridepublic Address clone() {try {return (Address) super.clone();} catch (CloneNotSupportedException e) {// 這種情況不應該發生,因為我們實現了Cloneablethrow new RuntimeException("Clone not supported", e);}}// Getter和Setter方法public String getCity() { return city; }public void setCity(String city) { this.city = city; }public String getStreet() { return street; }public void setStreet(String street) { this.street = street; }public String getZipCode() { return zipCode; }public void setZipCode(String zipCode) { this.zipCode = zipCode; }@Overridepublic String toString() {return "Address{city='" + city + "', street='" + street + "', zipCode='" + zipCode + "'}";}
}// 員工原型,包含復雜對象引用
public class Employee implements Prototype {private String name;private String department;private Address address;private List<String> skills;public Employee(String name, String department, Address address) {this.name = name;this.department = department;this.address = address;this.skills = new ArrayList<>();}// 深拷貝構造函數private Employee(Employee other) {this.name = other.name;this.department = other.department;// 深拷貝地址對象this.address = other.address != null ? other.address.clone() : null;// 深拷貝技能列表this.skills = new ArrayList<>(other.skills);}@Overridepublic Prototype clone() {return new Employee(this);}public void addSkill(String skill) {skills.add(skill);}// Getter和Setter方法public String getName() { return name; }public void setName(String name) { this.name = name; }public String getDepartment() { return department; }public void setDepartment(String department) { this.department = department; }public Address getAddress() { return address; }public void setAddress(Address address) { this.address = address; }public List<String> getSkills() { return skills; }@Overridepublic String toString() {return "Employee{name='" + name + "', department='" + department + "', address=" + address + ", skills=" + skills + "}";}
}

6.3 序列化克隆實現

業務背景: 使用序列化方式實現深拷貝,適用于復雜對象圖。

import java.io.*;// 支持序列化克隆的基類
public abstract class SerializablePrototype implements Prototype, Serializable {private static final long serialVersionUID = 1L;@Overridepublic Prototype clone() {try {// 使用序列化進行深拷貝ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);oos.close();ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);Prototype cloned = (Prototype) ois.readObject();ois.close();return cloned;} catch (IOException | ClassNotFoundException e) {throw new RuntimeException("Serialization clone failed", e);}}
}// 使用序列化克隆的配置對象
public class Configuration extends SerializablePrototype {private String environment;private Map<String, String> properties;private List<String> servers;public Configuration(String environment) {this.environment = environment;this.properties = new HashMap<>();this.servers = new ArrayList<>();}public void addProperty(String key, String value) {properties.put(key, value);}public void addServer(String server) {servers.add(server);}// Getter方法public String getEnvironment() { return environment; }public Map<String, String> getProperties() { return properties; }public List<String> getServers() { return servers; }@Overridepublic String toString() {return "Configuration{environment='" + environment + "', properties=" + properties + ", servers=" + servers + "}";}
}

6.4 實際業務場景:文檔模板系統

業務背景: 實現文檔模板系統,支持快速復制和定制不同類型的文檔。

// 文檔接口
public interface Document extends Prototype {void setTitle(String title);void setContent(String content);String getTitle();String getContent();
}// 報告文檔原型
public class ReportDocument implements Document {private String title;private String content;private String author;private Date createDate;private List<String> sections;public ReportDocument() {this.createDate = new Date();this.sections = new ArrayList<>();// 預設報告模板結構this.sections.add("摘要");this.sections.add("背景");this.sections.add("分析");this.sections.add("結論");}// 拷貝構造函數private ReportDocument(ReportDocument other) {this.title = other.title;this.content = other.content;this.author = other.author;this.createDate = new Date(); // 新文檔使用當前時間this.sections = new ArrayList<>(other.sections);}@Overridepublic Prototype clone() {return new ReportDocument(this);}@Overridepublic void setTitle(String title) { this.title = title; }@Overridepublic void setContent(String content) { this.content = content; }@Overridepublic String getTitle() { return title; }@Overridepublic String getContent() { return content; }public void setAuthor(String author) { this.author = author; }public String getAuthor() { return author; }public List<String> getSections() { return sections; }@Overridepublic String toString() {return "ReportDocument{title='" + title + "', author='" + author + "', sections=" + sections.size() + ", createDate=" + createDate + "}";}
}// 合同文檔原型
public class ContractDocument implements Document {private String title;private String content;private String partyA;private String partyB;private Date effectiveDate;private BigDecimal amount;public ContractDocument() {this.effectiveDate = new Date();this.amount = BigDecimal.ZERO;}private ContractDocument(ContractDocument other) {this.title = other.title;this.content = other.content;this.partyA = other.partyA;this.partyB = other.partyB;this.effectiveDate = new Date(); // 新合同使用當前日期this.amount = other.amount;}@Overridepublic Prototype clone() {return new ContractDocument(this);}@Overridepublic void setTitle(String title) { this.title = title; }@Overridepublic void setContent(String content) { this.content = content; }@Overridepublic String getTitle() { return title; }@Overridepublic String getContent() { return content; }// 合同特有方法public void setPartyA(String partyA) { this.partyA = partyA; }public void setPartyB(String partyB) { this.partyB = partyB; }public void setAmount(BigDecimal amount) { this.amount = amount; }@Overridepublic String toString() {return "ContractDocument{title='" + title + "', partyA='" + partyA + "', partyB='" + partyB + "', amount=" + amount + "}";}
}// 文檔管理器
public class DocumentManager {private static final PrototypeRegistry registry = new PrototypeRegistry();static {// 初始化文檔模板ReportDocument reportTemplate = new ReportDocument();reportTemplate.setTitle("月度報告模板");reportTemplate.setAuthor("系統管理員");ContractDocument contractTemplate = new ContractDocument();contractTemplate.setTitle("標準合同模板");contractTemplate.setPartyA("甲方公司");registry.addPrototype("report", reportTemplate);registry.addPrototype("contract", contractTemplate);}public static Document createDocument(String type, String title) {Document doc = (Document) registry.getPrototype(type);doc.setTitle(title);return doc;}
}// 客戶端使用示例
public class DocumentClient {public static void main(String[] args) {// 創建報告文檔Document report1 = DocumentManager.createDocument("report", "Q1財務報告");report1.setContent("第一季度財務分析內容...");Document report2 = DocumentManager.createDocument("report", "Q2財務報告");report2.setContent("第二季度財務分析內容...");// 創建合同文檔Document contract1 = DocumentManager.createDocument("contract", "軟件開發合同");contract1.setContent("軟件開發合同條款...");System.out.println("Report 1: " + report1);System.out.println("Report 2: " + report2);System.out.println("Contract: " + contract1);}// 總結:通過原型模式,文檔系統可快速創建各種類型文檔,提升效率和一致性。
}## 7. 測試用例**業務背景:** 驗證原型模式的核心功能,包括基本克隆、深拷貝和注冊表管理。```java
import org.junit.Test;
import static org.junit.Assert.*;public class PrototypePatternTest {@Testpublic void testBasicClone() {// 測試基本克隆功能ConcretePrototype original = new ConcretePrototype("test", 42);ConcretePrototype cloned = (ConcretePrototype) original.clone();// 驗證克隆對象與原對象不是同一個實例assertNotSame(original, cloned);// 驗證克隆對象的內容相同assertEquals(original.getField(), cloned.getField());assertEquals(original.getValue(), cloned.getValue());assertEquals(original, cloned);}@Testpublic void testPrototypeRegistry() {// 清空注冊表PrototypeRegistry.clear();// 注冊原型ConcretePrototype prototype = new ConcretePrototype("template", 100);PrototypeRegistry.addPrototype("test", prototype);// 獲取克隆對象Prototype cloned = PrototypeRegistry.getPrototype("test");ConcretePrototype clonedConcrete = (ConcretePrototype) cloned;assertEquals("template", clonedConcrete.getField());assertEquals(100, clonedConcrete.getValue());assertNotSame(prototype, cloned);}@Testpublic void testDeepCopy() {// 測試深拷貝Address address = new Address("北京", "中關村大街", "100080");Employee original = new Employee("張三", "技術部", address);original.addSkill("Java");original.addSkill("Spring");Employee cloned = (Employee) original.clone();// 驗證深拷貝:修改克隆對象的地址不影響原對象cloned.getAddress().setCity("上海");cloned.addSkill("Python");assertEquals("北京", original.getAddress().getCity());assertEquals("上海", cloned.getAddress().getCity());assertEquals(2, original.getSkills().size());assertEquals(3, cloned.getSkills().size());}@Testpublic void testDocumentSystem() {// 測試文檔模板系統Document report1 = DocumentManager.createDocument("report", "Q1報告");Document report2 = DocumentManager.createDocument("report", "Q2報告");// 驗證不同的文檔實例assertNotSame(report1, report2);assertEquals("Q1報告", report1.getTitle());assertEquals("Q2報告", report2.getTitle());// 驗證報告文檔的特定屬性assertTrue(report1 instanceof ReportDocument);assertTrue(report2 instanceof ReportDocument);}@Testpublic void testRegistryExceptionHandling() {// 測試注冊表異常處理assertThrows(IllegalArgumentException.class, () -> {PrototypeRegistry.addPrototype(null, new ConcretePrototype("test", 1));});assertThrows(IllegalArgumentException.class, () -> {PrototypeRegistry.addPrototype("test", null);});assertThrows(IllegalArgumentException.class, () -> {PrototypeRegistry.getPrototype("nonexistent");});}
}

8. 常見誤區與反例

8.1 常見誤區

  • 誤區1 :淺拷貝導致引用共享

    // 錯誤示例:簡單的字段復制導致引用共享
    public class BadEmployee implements Prototype {private Address address;public Prototype clone() {BadEmployee clone = new BadEmployee();clone.address = this.address; // 淺拷貝,共享引用return clone;}
    }
    

    正確做法:實現深拷貝,確保引用對象也被克隆。

  • 誤區2 :原型注冊表未做防護

    // 錯誤示例:直接返回原型對象
    public static Prototype getPrototype(String key) {return prototypes.get(key); // 返回原始對象,可能被修改
    }
    

    正確做法:始終返回克隆對象,保護原型不被修改。

  • 誤區3 :忽略克隆中的資源管理

    // 錯誤示例:資源句柄直接克隆
    public class BadResource implements Prototype {private FileInputStream inputStream;public Prototype clone() {BadResource clone = new BadResource();clone.inputStream = this.inputStream; // 資源不能共享return clone;}
    }
    

8.2 反例分析

  • 反例1 :不可變對象使用原型模式
    對于StringInteger等不可變對象,使用原型模式沒有意義,應直接重用。

  • 反例2 :系統資源句柄克隆
    文件句柄、網絡連接、數據庫連接等系統資源不能簡單克隆,需要重新創建。

  • 反例3 :過度使用原型模式
    對于簡單對象,直接使用構造函數創建更簡單高效,不需要原型模式。

9. 最佳實踐

9.1 設計原則

  1. 深拷貝實現 :優先實現深拷貝,避免引用共享問題

    // 推薦:使用拷貝構造函數
    private Employee(Employee other) {this.name = other.name;this.address = other.address != null ? other.address.clone() : null;this.skills = new ArrayList<>(other.skills);
    }
    
  2. 注冊表防護 :注冊表應返回克隆對象,保護原型安全

    // 推薦:防護性克隆
    public static Prototype getPrototype(String key) {Prototype prototype = prototypes.get(key);return prototype != null ? prototype.clone() : null;
    }
    
  3. 異常與資源管理 :妥善處理克隆過程中的異常和資源

    // 推薦:完善的異常處理
    @Override
    public Prototype clone() {try {MyClass cloned = (MyClass) super.clone();cloned.resource = createNewResource(); // 重新創建資源return cloned;} catch (CloneNotSupportedException e) {throw new RuntimeException("Clone failed", e);}
    }
    

9.2 性能優化

  1. 克隆策略選擇 :根據對象復雜度選擇合適的克隆策略

    • 簡單對象:拷貝構造函數
    • 復雜對象:序列化克隆
    • 不可變部分:引用復制
  2. 延遲克隆 :對于大對象,考慮寫時復制(Copy-on-Write)策略

    // 推薦:寫時復制優化
    public class LazyCloneList implements Prototype {private List<String> data;private boolean isCloned = false;private void ensureCloned() {if (!isCloned) {data = new ArrayList<>(data);isCloned = true;}}public void add(String item) {ensureCloned();data.add(item);}
    }
    

9.3 架構設計

  1. 與工廠模式結合 :原型注冊表可與工廠模式結合,提供統一的對象創建接口

  2. 線程安全考慮 :在多線程環境下,確保原型注冊表和克隆操作的線程安全

    // 推薦:線程安全的注冊表
    public class ThreadSafeRegistry {private static final ConcurrentHashMap<String, Prototype> prototypes = new ConcurrentHashMap<>();
    }
    
  3. 版本控制 :為原型對象添加版本信息,支持向后兼容的序列化克隆

10. 參考資料與延伸閱讀

  • 《設計模式:可復用面向對象軟件的基礎》GoF
  • Effective Java(中文版)
  • https://refactoringguru.cn/design-patterns/prototype
  • https://www.baeldung.com/java-prototype-pattern

本文為設計模式系列第8篇,后續每篇將聚焦一個設計模式或設計原則,深入講解實現與應用,敬請關注。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86812.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86812.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86812.shtml

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

相關文章

區塊鏈到底是什么?

區塊鏈本質上是一種去中心化的分布式賬本技術&#xff0c;具有以下核心特點&#xff1a; - 去中心化&#xff1a;沒有中央管理機構&#xff0c;數據由網絡中的多個節點共同維護&#xff0c;比如比特幣網絡中各個節點都保存著完整賬本。 - 分布式存儲&#xff1a;數據不是存在一…

系統架構設計師論文分享-論ATAM的使用

我的軟考歷程 摘要 2023年2月&#xff0c;我司通過了研發紗線MES系統的立項&#xff0c;該系統為國內紗線工廠提供SAAS服務&#xff0c;旨在提高紗線工廠的數字化和智能化水平。我在本項目中擔任系統架構設計師&#xff0c;負責整個項目的架構設計工作。本文結合我在該項目中…

vue-28(服務器端渲染(SSR)簡介及其優勢)

服務器端渲染&#xff08;SSR&#xff09;簡介及其優勢 服務器端渲染&#xff08;SSR&#xff09;是現代網絡應用的關鍵技術&#xff0c;特別是使用 Vue.js 等框架構建的應用。它通過在服務器上渲染初始應用狀態來彌補傳統單頁應用&#xff08;SPA&#xff09;的局限性&#x…

工業電子 | 什么是SerDes,為何工業和汽車應用需要它?

重點內容速覽&#xff1a; 1. 什么是SerDes&#xff1f; 2. ADI&#xff1a;私有協議的GMSL將向公有協議轉變 3. TI&#xff1a;工業和汽車有兩套SerDes解決方案 4. Microchip&#xff1a;推出通用協議SerDes芯片 5. 羅姆&#xff1a;主要針對汽車領域 6. 國產SerDes芯…

大事件項目記錄4-用戶接口開發-更新用戶基本信息

4&#xff09;更新用戶基本信息。 UserController.java&#xff1a; UserMapper.java&#xff1a; Update("update user set nickname #{nickname},email #{email},update_time #{updateTime} where id #{id}")void update(User user); UserServiceInterface…

Transformer結構--輸入編碼(BPE,PE)

在Transformer結構中&#xff0c;輸入編碼是模型處理文本數據的關鍵步驟&#xff0c;其中**BPE&#xff08;Byte Pair Encoding&#xff0c;字節對編碼&#xff09;和PE&#xff08;Positional Encoding&#xff0c;位置編碼&#xff09;**是兩種重要的編碼方式&#xff0c;它們…

Confluence-測試用例設計指導方法

測試經驗知識庫 典型的測試場景驗證點各個項目有價值的經驗和測試點 測試經驗知識庫 - 草稿測試用例執行量化指導建議 何時需要進行全量測試和如何定義和執行測試用例量的一些建議和標準 端對端&#xff08;E2E&#xff09;測試用例設計指導方案 在測試行業中&#xff0c;端到端…

淺析JVM

一、JVM運行流程 如圖&#xff1a; JVM由四個部分構成&#xff1a; 1.類加載器 加載類文件到內存2.運行時數據區 寫的程序需要加載到這里才能運行3.執行引擎 負責解釋命令&#xff0c;提交操作系統執行4.本地接口 融合不同編程語言為java所用&#xff0c;如Java程序驅動打印…

多個 Job 并發運行時共享配置文件導致上下文污染,固化 Jenkins Job 上下文

基于 context.py 固化 Jenkins Job 上下文的完整方案&#xff0c;適用于你當前的工作流&#xff08;Python Jenkins Pipeline&#xff09;&#xff0c;解決&#xff1a; 多個 Job 并發運行時共享配置文件導致上下文污染&#xff1b;讀取環境變量或 JSON 文件時被其他 Job 修改…

簡木易支付系統 功能齊全,對接接口超多

簡木易支付系統&#xff0c;作為一款引領行業潮流的卓越支付解決方案&#xff0c;依托先進的 PHP MySQL 技術架構精心打造。在開發過程中&#xff0c;它巧妙運用了功能強大的 ThinkPHP8 框架&#xff0c;完美融合前端主流技術 Vue、Element 以及 Layuiadmin&#xff0c;共同鑄…

【軟考高項論文】信息系統項目的人力資源管理

摘要 本文圍繞信息系統項目的人力資源管理展開論述。以我在2024年參與的為大型國有企業構建供應鏈管理系統項目為例&#xff0c;闡述了項目人力資源管理的主要流程&#xff0c;包括規劃、組建、建設和管理團隊四個過程&#xff0c;以及所運用的工具和理論。同時&#xff0c;分…

【EI會議征稿】東北大學主辦第三屆機器視覺、圖像處理與影像技術國際會議(MVIPIT 2025)

一、會議信息 大會官網&#xff1a;www.mvipit.org 官方郵箱&#xff1a;mvipit163.com 會議地點&#xff1a;遼寧沈陽 主辦單位&#xff1a;東北大學 會議時間&#xff1a;2025 年 9 月 27 日-9 月 29 日 二、征稿主題 集中但不限于“機器視覺、圖像處理與影像技術”等其…

從零開始的云計算生活——第二十三天,稍作休息,Tomcat

目錄 一.故事背景 二.Tomcat概述 1、Tomcat介紹 2、Tomcat歷史 二、Tomcat原理分析 1、Http工作原理 2、Tomcat整體架構 3、Coyote連接器架構 4、Catalina容器架構 5、Jasper處理流程 6、JSP編譯過程 7、Tomcat啟動流程 8、Tomcat請求處理流程 三、Tomcat安裝與配…

幾種基于Doherty結構的GAN氮化鎵功放設計方法介紹

功率放大器是現代無線通信系統中最重要的組件之一。理想情況下&#xff0c;它們能夠以高線性度和高效率提供高輸出功率。但通常在這三個關鍵的功率放大器性能參數之間需要進行權衡取舍&#xff0c;而且具有最高輸出功率和線性度的放大器往往會犧牲效率。 在支持寬帶寬和高數據…

前端打印計算單位 cm、mm、px

A4 縱向 寬&#xff1a;21cm&#xff0c;210mm&#xff0c;793.698px 高&#xff1a;29.7cm&#xff0c;297mm&#xff0c;1122.520px A4 橫向 寬&#xff1a;29.7cm&#xff0c;297mm&#xff0c;1122.520px 高&#xff1a;21cm&#xff0c;210mm&#xff0c;793.698px …

c# sugersql 獲取子表數據排序

在C#中使用Sugar ORM&#xff08;一個流行的.NET ORM框架&#xff09;獲取子表數據并進行排序&#xff0c;可以通過以下幾種方式實現&#xff1a; 1. 使用HasMany或HasOne配置 首先&#xff0c;確保你在配置實體時已經正確設置了HasMany或HasOne關系。例如&#xff0c;假設你…

【nRF52832】【環境搭建 3】【如何新建一個純單片機開發的工程】

1. 前言 笨叔&#xff0c;又要開始扯淡了!!! 不感興趣的同學&#xff0c;可以跳過了!!! 笨叔之前在大學里面&#xff0c; 剛接觸單片機時。就被 windows 平臺 例如 keill 5 、IAR 等一堆開會環境差點勸退。 當時也是堅持咬牙一點點摸索過來的。剛摸索明白&#xff0c;覺得單片…

Spring-loC與DI

目錄 1 loC控制反轉思想 2 DI依賴注入 3 loC詳解 3.1 存儲Bean &#xff08;1&#xff09;Controller &#xff08;2&#xff09;Service &#xff08;3&#xff09;Repository &#xff08;4&#xff09;Component &#xff08;5&#xff09;Configuration &#xf…

職業本科單片機與嵌入式技術實訓室建設設想

一、引言 在當今數字化與智能化飛速發展的時代&#xff0c;單片機與嵌入式技術作為信息技術領域的關鍵支撐&#xff0c;廣泛應用于工業控制、智能家居、物聯網、汽車電子等眾多行業&#xff0c;成為推動產業升級和創新發展的核心驅動力。職業本科教育旨在培養適應生產、建設、…

傳統消防演練與 VR 消防演練的區別有哪些

演練形式&#xff1a;傳統消防演練往往依托真實的場地&#xff0c;像空曠的廣場、廢棄的建筑物或是專門的消防訓練基地等。參與者能觸摸并使用實實在在的消防設備&#xff0c;例如干粉滅火器、二氧化碳滅火器、消防水帶等。在演練時&#xff0c;會通過點燃模擬火源、釋放煙霧等…