零基礎設計模式——行為型模式 - 模板方法模式

第四部分:行為型模式 - 模板方法模式 (Template Method Pattern)

現在我們來學習模板方法模式。這個模式在一個方法中定義一個算法的骨架,而將一些步驟延遲到子類中實現。模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。

  • 核心思想:定義一個操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。

模板方法模式 (Template Method Pattern)

“定義一個操作中的算法的骨架(骨架步驟的順序),而將一些步驟(具體實現)延遲到子類中。模板方法使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。” (Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.)

想象一下制作一杯飲料(比如咖啡或茶)的過程:

  1. 把水燒開 (Boil Water) - 這是一個通用步驟。
  2. 沖泡 (Brew) - 咖啡是沖泡咖啡粉,茶是浸泡茶葉。這是可變步驟。
  3. 把飲料倒進杯子 (Pour in Cup) - 這是一個通用步驟。
  4. 加調料 (Add Condiments) - 咖啡可能加糖和牛奶,茶可能加檸檬。這是可變步驟,并且可能是可選的。

模板方法模式就是把這個制作流程(算法骨架)定義在一個抽象類(比如 BeverageMaker)的模板方法(比如 prepareBeverage())中:

prepareBeverage() {boilWater();      // 具體方法,父類實現brew();           // 抽象方法,子類實現pourInCup();      // 具體方法,父類實現if (customerWantsCondiments()) { // 鉤子方法,子類可覆蓋addCondiments(); // 抽象方法,子類實現}
}
  • boilWater()pourInCup() 是所有飲料制作共通的,可以在父類中直接實現。
  • brew()addCondiments() 是具體飲料不同的,聲明為抽象方法,由子類(如 CoffeeMakerTeaMaker)去實現。
  • customerWantsCondiments() 是一個“鉤子 (hook)”方法,父類可以提供一個默認實現(比如默認需要調料),子類可以覆蓋它來改變算法的某個特定點(比如某個子類飲料默認不需要調料,或者提供更復雜的判斷邏輯)。

這樣,算法的整體結構(燒水 -> 沖泡 -> 倒杯 -> 可能加調料)被固定下來了,但具體的沖泡內容和調料可以由子類自由定義。

1. 目的 (Intent)

模板方法模式的主要目的:

  1. 定義算法骨架:在一個抽象類中定義一個算法的框架,明確算法的執行步驟和順序。
  2. 延遲實現可變步驟:將算法中可變的步驟的實現推遲到子類中。
  3. 代碼復用:將算法中不變的部分(公共步驟)放在父類中,避免在子類中重復代碼。
  4. 控制子類擴展:父類通過模板方法控制算法的整體流程,子類只能在指定的可變點上進行擴展,而不能改變算法的結構。

2. 生活中的例子 (Real-world Analogy)

  • 食譜 (Recipe)

    • 模板方法:一道菜的烹飪流程(準備食材、切菜、炒制、調味、裝盤)。
    • 具體步驟:不同的菜肴在“準備食材”、“炒制方法”、“調味料”等方面有不同的實現。
  • 房屋建造流程

    • 模板方法:打地基 -> 建墻體 ->封頂 -> 內部裝修 -> 外部裝修。
    • 具體步驟:不同的房屋類型(別墅、公寓)在“墻體材料”、“裝修風格”等方面有不同的實現。
  • 軟件開發生命周期 (SDLC)

    • 模板方法:需求分析 -> 設計 ->編碼 -> 測試 -> 部署 -> 維護。
    • 具體步驟:不同的項目或團隊可能在“設計方法論”(如敏捷、瀑布)、“測試策略”等方面有不同的具體做法。
  • 簡歷模板

    • 模板方法:個人信息 -> 教育背景 -> 工作經歷 -> 項目經驗 -> 技能證書。
    • 具體步驟:每個人填寫的具體內容不同。

3. 結構 (Structure)

模板方法模式通常包含以下角色:

  1. AbstractClass (抽象類)

    • 定義一個或多個抽象操作(primitiveOperation),由具體子類實現這些操作。
    • 定義一個模板方法(templateMethod),該方法實現了一個算法的骨架。模板方法會調用抽象操作、具體操作以及鉤子操作。
    • 可以包含一些具體操作(concreteOperation),這些操作對所有子類都是相同的。
    • 可以包含鉤子操作(hookOperation),通常在抽象類中提供一個默認實現(或者為空實現),子類可以根據需要覆蓋它們來影響算法的流程。
  2. ConcreteClass (具體類)

    • 繼承自 AbstractClass。
    • 實現父類中定義的抽象操作。
    • 可以覆蓋父類中的鉤子操作。
      在這里插入圖片描述

模板方法中的操作類型

  • 具體操作 (Concrete Operations):在抽象類中實現,子類可以直接使用或繼承。
  • 抽象操作 (Abstract Operations / Primitive Operations):在抽象類中聲明(通常為抽象方法),必須由子類實現。
  • 鉤子操作 (Hook Operations):在抽象類中提供一個默認實現(可能是空實現)。子類可以選擇性地覆蓋這些方法,以在算法的特定點“掛鉤”并改變算法的行為。鉤子常用于:
    • 讓子類能夠對算法的某一步進行可選的擴展。
    • 讓子類能夠決定算法的某一步是否執行。

模板方法通常被聲明為 final (Java) 或在 Go 中通過非導出方法和導出方法組合的方式(父類調用非導出的可被子類“覆蓋”的方法)來防止子類改變算法的整體結構。

4. 適用場景 (When to Use)

  • 當你想一次性實現一個算法的不變部分,并將可變的行為留給子類來實現時。
  • 當各個子類中公共的行為應被提取出來并集中到一個公共父類中以避免代碼重復時。首先識別現有代碼中的不同之處,然后將不同之處分離為新的操作。最后,用一個調用這些新操作的模板方法來替換這些不同的代碼。
  • 當需要控制子類的擴展時。模板方法只在特定點調用鉤子操作,這就允許在這些點進行擴展,而不是在其他地方。
  • 框架開發:框架通常定義了整體的執行流程(模板方法),而應用程序開發者通過繼承框架中的類并實現特定的抽象方法或鉤子方法來定制應用行為。

5. 優缺點 (Pros and Cons)

優點:

  1. 代碼復用:將公共代碼放在抽象父類中,提高了代碼復用性。
  2. 封裝不變部分,擴展可變部分:算法的骨架(不變部分)在父類中定義和控制,可變部分由子類實現,易于擴展。
  3. 符合開閉原則:對擴展開放(可以通過增加子類來實現新的行為),對修改關閉(不需要修改父類的模板方法)。
  4. 控制反轉 (Inversion of Control - IoC):父類調用子類的操作,而不是子類調用父類。這是一種簡單的 IoC 形式,有時被稱為“好萊塢原則”——“不要給我們打電話,我們會給你打電話 (Don’t call us, we’ll call you)”。

缺點:

  1. 類的數量增加:每個不同的算法變體都需要一個單獨的子類,可能會導致類的數量增多。
  2. 繼承的限制:模板方法模式基于繼承,這帶來了一些固有的限制。例如,子類必須繼承抽象父類,如果子類已經有了其他父類(在不支持多重繼承的語言中),則無法使用此模式。
  3. 算法骨架固定:算法的整體流程由父類固定,如果需要對流程本身進行大的改動,可能會比較困難,可能需要修改父類的模板方法。
  4. 可讀性可能降低:如果模板方法中的步驟過多,或者鉤子方法的使用比較復雜,可能會使得理解算法的整體流程和子類的具體實現之間的關系變得困難。

6. 實現方式 (Implementations)

讓我們以制作不同類型的報告(例如,文本報告和HTML報告)為例。報告生成的流程可能包括:初始化、格式化頭部、格式化主體內容、格式化尾部、輸出。

抽象類 (ReportGenerator)
// report_generator.go (AbstractClass and its methods)
package templateimport "fmt"// ReportGenerator 抽象類 (通過接口和嵌入結構體模擬)
// Go 中沒有直接的抽象類,通常用接口定義行為,用結構體嵌入實現通用部分
// 或者定義一個包含未實現方法的結構體,讓具體子類去“填充”這些方法。
// 這里我們采用一種更接近傳統模板方法模式的結構:
// 一個包含模板方法的結構體,它調用由嵌入的“子類”接口實現的方法。// ReportSteps 定義了子類需要實現的步驟
type ReportSteps interface {initialize()formatHeader() stringformatBody() stringformatFooter() stringoutputReport(header, body, footer string)hookBeforeBody() // 鉤子方法
}// BaseReportGenerator 包含模板方法和通用邏輯
type BaseReportGenerator struct {steps ReportSteps // 指向具體實現這些步驟的對象 (子類)
}// NewBaseReportGenerator 構造函數,需要傳入具體的步驟實現者
func NewBaseReportGenerator(steps ReportSteps) *BaseReportGenerator {return &BaseReportGenerator{steps: steps}
}// GenerateReport 模板方法
func (rg *BaseReportGenerator) GenerateReport() {rg.steps.initialize() // 調用子類實現的初始化header := rg.steps.formatHeader() // 調用子類實現的頭部格式化rg.steps.hookBeforeBody() // 調用鉤子方法body := rg.steps.formatBody() // 調用子類實現的身體格式化footer := rg.steps.formatFooter() // 調用子類實現的尾部格式化rg.steps.outputReport(header, body, footer) // 調用子類實現的輸出fmt.Println("Report generation complete.")
}// --- 為了讓具體類能調用到BaseReportGenerator的方法,或者讓BaseReportGenerator能調用具體類的方法
// Go 的實現方式與 Java/C++ 的繼承有區別。一種常見做法是具體類持有 BaseReportGenerator,
// 或者 BaseReportGenerator 持有具體步驟的實現者(如上面的 ReportSteps)。
// 下面的具體類將實現 ReportSteps 接口。
// ReportGenerator.java (AbstractClass)
package com.example.template;public abstract class ReportGenerator {// Template method - final to prevent overriding the algorithm structurepublic final void generateReport() {initialize(); // Common step, or could be abstract/hookString header = formatHeader(); // Step to be implemented by subclasshookBeforeBody(); // Hook methodString body = formatBody(); // Step to be implemented by subclassString footer = formatFooter(); // Step to be implemented by subclassoutputReport(header, body, footer); // Common step, or could be abstract/hookSystem.out.println("Report generation complete.");}// Common methods (can be overridden if not final)protected void initialize() {System.out.println("ReportGenerator: Initializing common report data...");}protected void outputReport(String header, String body, String footer) {System.out.println("ReportGenerator: --- Final Report ---");System.out.println(header);System.out.println(body);System.out.println(footer);System.out.println("ReportGenerator: --- End of Report ---");}// Abstract methods (primitive operations) - to be implemented by subclassesprotected abstract String formatHeader();protected abstract String formatBody();protected abstract String formatFooter();// Hook method - subclass can override, but not mandatoryprotected void hookBeforeBody() {// Default implementation does nothingSystem.out.println("ReportGenerator: (Hook) No specific action before body by default.");}
}
具體類 (TextReportGenerator, HtmlReportGenerator)
// text_report_generator.go (ConcreteClass)
package templateimport "fmt"// TextReportGenerator 具體類
type TextReportGenerator struct {// 可以嵌入 BaseReportGenerator 來繼承其方法,但Go的模板方法通常不這么做// 或者讓 BaseReportGenerator 持有 TextReportGenerator 的實例 (通過 ReportSteps 接口)data string // 示例數據
}func NewTextReportGenerator(data string) *TextReportGenerator {return &TextReportGenerator{data: data}
}// 實現 ReportSteps 接口
func (tr *TextReportGenerator) initialize() {fmt.Println("TextReport: Initializing text report specific data...")
}func (tr *TextReportGenerator) formatHeader() string {return "=== TEXT REPORT HEADER ==="
}func (tr *TextReportGenerator) formatBody() string {return fmt.Sprintf("Body: %s\n(Rendered as plain text)", tr.data)
}func (tr *TextReportGenerator) formatFooter() string {return "--- TEXT REPORT FOOTER ---"
}func (tr *TextReportGenerator) outputReport(header, body, footer string) {fmt.Println("TextReport: Outputting to console:")fmt.Println(header)fmt.Println(body)fmt.Println(footer)
}func (tr *TextReportGenerator) hookBeforeBody() {fmt.Println("TextReport: (Hook) Adding a small note before text body.")
}// html_report_generator.go (ConcreteClass)
package templateimport "fmt"// HtmlReportGenerator 具體類
type HtmlReportGenerator struct {data string
}func NewHtmlReportGenerator(data string) *HtmlReportGenerator {return &HtmlReportGenerator{data: data}
}func (hr *HtmlReportGenerator) initialize() {fmt.Println("HtmlReport: Initializing HTML report specific data (e.g., CSS links)...")
}func (hr *HtmlReportGenerator) formatHeader() string {return "<html>\n<head><title>HTML Report</title></head>\n<body>\n  <h1>HTML Report Header</h1>"
}func (hr *HtmlReportGenerator) formatBody() string {return fmt.Sprintf("  <p>Body: %s</p>\n  <em>(Rendered as HTML)</em>", hr.data)
}func (hr *HtmlReportGenerator) formatFooter() string {return "  <hr/>\n  <footer>HTML Report Footer</footer>\n</body>\n</html>"
}func (hr *HtmlReportGenerator) outputReport(header, body, footer string) {fmt.Println("HtmlReport: Simulating saving to an HTML file:")fmt.Println(header)fmt.Println(body)fmt.Println(footer)
}func (hr *HtmlReportGenerator) hookBeforeBody() {// HTML報告可能不需要這個鉤子,或者有不同的實現fmt.Println("HtmlReport: (Hook) Adding a meta tag or script before HTML body.")
}
// TextReportGenerator.java (ConcreteClass)
package com.example.template;public class TextReportGenerator extends ReportGenerator {private String data;public TextReportGenerator(String data) {this.data = data;}@Overrideprotected void initialize() {super.initialize(); // Call common initialization if neededSystem.out.println("TextReport: Initializing text report specific data...");}@Overrideprotected String formatHeader() {return "=== TEXT REPORT HEADER ===";}@Overrideprotected String formatBody() {return "Body: " + this.data + "\n(Rendered as plain text)";}@Overrideprotected String formatFooter() {return "--- TEXT REPORT FOOTER ---";}@Overrideprotected void outputReport(String header, String body, String footer) {// Override if text report needs a different output mechanismSystem.out.println("TextReport: Outputting to console:");System.out.println(header);System.out.println(body);System.out.println(footer);}@Overrideprotected void hookBeforeBody() {System.out.println("TextReport: (Hook) Adding a small note before text body.");}
}// HtmlReportGenerator.java (ConcreteClass)
package com.example.template;public class HtmlReportGenerator extends ReportGenerator {private String data;public HtmlReportGenerator(String data) {this.data = data;}@Overrideprotected String formatHeader() {return "<html>\n<head><title>HTML Report</title></head>\n<body>\n  <h1>HTML Report Header</h1>";}@Overrideprotected String formatBody() {return "  <p>Body: " + this.data + "</p>\n  <em>(Rendered as HTML)</em>";}@Overrideprotected String formatFooter() {return "  <hr/>\n  <footer>HTML Report Footer</footer>\n</body>\n</html>";}// We can use the default initialize() and outputReport() from ReportGenerator// or override them if specific HTML logic is needed.// Override hook if needed@Overrideprotected void hookBeforeBody() {System.out.println("HtmlReport: (Hook) Adding a meta tag or script before HTML body.");}
}
客戶端使用
// main.go (示例用法)
/*
package mainimport ("./template""fmt"
)func main() {fmt.Println("--- Generating Text Report ---")textData := "This is the data for the text report."textReportSteps := template.NewTextReportGenerator(textData)textReportGenerator := template.NewBaseReportGenerator(textReportSteps)textReportGenerator.GenerateReport()fmt.Println("\n--- Generating HTML Report ---")htmlData := "This is the data for the HTML report."htmlReportSteps := template.NewHtmlReportGenerator(htmlData)htmlReportGenerator := template.NewBaseReportGenerator(htmlReportSteps)htmlReportGenerator.GenerateReport()
}
*/
// Main.java (示例用法)
/*
package com.example;import com.example.template.HtmlReportGenerator;
import com.example.template.ReportGenerator;
import com.example.template.TextReportGenerator;public class Main {public static void main(String[] args) {System.out.println("--- Generating Text Report ---");String textData = "This is the data for the text report.";ReportGenerator textReport = new TextReportGenerator(textData);textReport.generateReport();System.out.println("\n--- Generating HTML Report ---");String htmlData = "This is the data for the HTML report.";ReportGenerator htmlReport = new HtmlReportGenerator(htmlData);htmlReport.generateReport();}
}
*/

7. 總結

模板方法模式是一種基于繼承的代碼復用技術。它允許我們定義一個算法的骨架,并將算法中某些步驟的實現延遲到子類。這使得子類可以在不改變算法整體結構的前提下,重新定義算法的特定步驟。該模式在框架設計中非常常見,因為它提供了一種標準化的方式來構建可擴展的組件。通過合理使用抽象方法和鉤子方法,可以在固定算法流程和提供靈活性之間找到一個很好的平衡點。

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

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

相關文章

android通過adb push apk放置目錄/sdcard/Download/下無法安裝

本文通過對源碼進行追蹤,并且調試各種方式,得出android通過adb push apk放置目錄/sdcard/Download/下無法安裝的原因,并從兩個修改點觸發,提出如何能修復此問題的建議。 1. 現象 把apk通過adb push的方式放在/sdcard/Download文件夾下, (1)直接打開File(DocumentUI)…

Spring Boot整合PF4J:構建動態插拔的組件化架構

前言 在當今快速迭代的軟件開發領域,業務需求的頻繁變更對系統架構的靈活性和可擴展性提出了極高要求。傳統的單體應用架構在面對功能的不斷新增和修改時,往往會陷入代碼臃腫、維護困難、擴展性差的困境。組件化開發,為解決這些問題提供了新的思路,通過實現組件的動態插拔…

剃須效率低?電鑄多孔刀網設計如何提升毛發捕捉率

剃須效率低下常源于刀網對毛發的捕捉能力不足——傳統沖壓刀網因孔型單一、邊緣毛刺等問題&#xff0c;導致胡須滑脫或拉扯。而電鑄多孔刀網通過精密工藝革新&#xff0c;將毛發捕捉率提升40%以上。其核心優勢在于三維立體孔型設計與微米級精度控制&#xff0c;以下是技術解析&…

進一步了解git

1、什么是集中式&#xff1f;什么是分布式&#xff1f; SVN&#xff08;集中式&#xff09; 單一中央倉庫&#xff1a;所有代碼和歷史版本集中存儲在中央服務器&#xff0c;用戶本地僅保存當前工作副本。 強依賴網絡&#xff1a;提交、查看歷史等操作需實時連接服務器&#xf…

一、react18+項目初始化

npx create-rect-app 項目名稱配置antd design mobile // 安裝 npm install --save antd-mobile // 在文件中直接引入使用 import { Button } from antd-mobile <Button></Button>更改webpack配置 // 1.安裝必要的包 npm install craco --save-dev // 2.修改pack…

Azure 資源清單

Azure 資源清單 作用前置條件安裝PowerShell 7.0驗證 Azure資源清單安裝配置如果有舊版本&#xff0c;導致新模塊安裝不上&#xff0c;進行強制安裝 PowerShell 登錄到 Azure基本命令輸出詳細信息效果圖展示 作用 官方文檔&#xff1a;https://github.com/microsoft/ARI?tabr…

S11的含義-信號完整性分析

S11的含義: PCB上的互連結構是線性無源的&#xff0c;在傳輸信號時激勵源只有一個&#xff0c;即驅動器發出的信號。如果正弦信號從端口1進入&#xff0c;根據S11定義&#xff0c;S11表示端口1出來的正弦信號和端口1進入的正弦信號的比值。工程上通常把S11稱為回波損耗(Return …

基于OpenCv(開源計算機視覺庫)的圖像旋轉匹配

OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一個開源的計算機視覺和機器學習軟件庫&#xff0c;具有跨平臺特性&#xff0c;廣泛應用于工業檢測、醫療影像分析、自動駕駛、無人機、機器人視覺等多個領域。 本項目解決了圖像模板匹配時的旋轉問題。傳…

Elasticsearch Open Inference API 新增對 Cohere 的 Rerank 3 模型支持

作者&#xff1a;來自 Elastic Serena Chou 及 Max Hniebergall 了解 Cohere reranking&#xff0c;如何將 Cohere 的 Rerank 3 模型與 Elasticsearch 的 open inference API 一起使用&#xff0c;以及 Elastic 在語義 reranking 方面的路線圖。 注&#xff1a;原文在 2024 年 …

九日集訓第六天

目錄 兩個數對之間最大的乘積差 三角形的最大周長 數組拆分 救生艇 擺動排序|| 分發餅干 最少操作使數組遞增 使數組唯一的最小增量 有效三角形的個數 兩個數對之間最大的乘積差 class Solution { public:int maxProductDifference(vector<int>& nums) {so…

【軟件工程】Waitress + Nginx 部署 Python Web 服務

下面是完整的 Windows 系統部署方案,使用 Waitress 作為 WSGI 服務器運行 Python 后端,Nginx 作為反向代理同時提供前端服務: 項目結構 text 復制 下載 myapp/ ├── backend/ # Python后端 │ ├── app.py # Flask應用入口 │ ├──…

JS數據類型檢測方法總結

在 JavaScript 中&#xff0c;數據類型檢測是開發中的常見需求。以下是主要檢測方法及其優缺點&#xff1a; 1. typeof 操作符 最基礎的檢測方式&#xff0c;返回類型字符串&#xff1a; typeof 42; // "number" typeof "hello"; // &qu…

AEO:從搜索引擎到答案引擎,AI時代搜索優化的新戰場

在 ChatGPT、DeepSeek、Google SGE 等生成式AI崛起的時代&#xff0c;搜索正在經歷一場根本性變革&#xff1a; 過去&#xff1a;搜索引擎優化&#xff08;SEO&#xff09; 現在&#xff1a;答案引擎優化&#xff08;AEO&#xff09; 當搜索結果開始由AI直接生成“答案”而非…

搭建Node.js服務器

1.基礎HTTP服務器: 添加了路由處理添加了404錯誤處理添加了服務器錯誤監聽 2.靜態資源服務器: 使用異步文件操作支持目錄自動索引(默認加載 index.html)自動檢測文件類型并設置正確Content-Type更完善的錯誤處理 3.處理GET請求參數 提供了一個HTML表單用于測試使用url模塊…

Linux grep 命令

grep 是 Linux/Unix 系統中用于文本搜索的強大工具&#xff0c;支持基于正則表達式的模式匹配。以下是其詳細用法及實際應用示例&#xff1a; 基本語法 grep [選項] 模式 [文件...]模式&#xff1a;要搜索的字符串或正則表達式。文件&#xff1a;可以是單個文件或多個文件&…

oracle 11g通過rman做備份和還原

ORACLE RMAN增量備份完整恢復測試 1.創建測試環境: 1.1.創建測試表空間 SQL> create tablespace tablespace1 datafile ‘/data/u01/app/oracle/oradata/orcl/tablespace1.dbf’ size 10m; SQL> 1.2.創建測試用戶并指定為默認表空間: SQL> create user user1 iden…

為什么TCP有粘包問題,而UDP沒有

TCP粘包問題源于其面向字節流的設計&#xff0c;而UDP無此問題因其基于數據報的傳輸機制。 &#x1f50d; 一、TCP粘包問題的原因 字節流傳輸特性 TCP將數據視為連續的字節流&#xff0c;而非獨立的消息包。發送端多次寫入的小數據可能被合并為一個TCP段發送&#xff1b;接收端…

ELM:Embodied Understanding of Driving Scenarios

1. ELM 的創新點與核心思路 ELM 的核心在于 “具身理解”(Embodied Understanding),即通過常識與環境交互并進行推理,這一理念適用于自動駕駛車輛、機器人和無人機等多種應用場景。具身智能體(Embodied Agent)需具備四大核心能力:首先,它能夠描述周圍環境,對交通物體的…

實景VR知識科普

實景VR的定義與技術特點 實景VR&#xff0c;即基于真實場景的虛擬現實技術&#xff0c;是通過計算機生成的三維環境&#xff0c;旨在模擬并再現真實世界場景。用戶佩戴VR設備&#xff08;如VR頭盔、手柄等&#xff09;后&#xff0c;能夠沉浸在一個高度仿真的虛擬環境中&#…

CppCon 2016 學習:ITERATOR HAIKU

這組幻燈片講解了 C 中**范圍&#xff08;Ranges&#xff09;和迭代器&#xff08;Iterators&#xff09;**的核心概念&#xff0c;特別是 C14 標準定義的五種迭代器類別&#xff0c;以及范圍的基本使用方式。我幫你理個思路&#xff1a; 1. RANGE-SEQUENCE: 元素范圍&#xf…