零基礎設計模式——行為型模式 - 狀態模式

第四部分:行為型模式 - 狀態模式 (State Pattern)

我們繼續學習行為型模式,接下來是狀態模式。這個模式允許一個對象在其內部狀態改變時改變它的行為,對象看起來就像是改變了它的類。

  • 核心思想:允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它的類。

狀態模式 (State Pattern)

“允許一個對象在其內部狀態改變時改變它的行為。對象看起來似乎修改了它的類。” (Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.)

想象一下一個自動售貨機:

  • 自動售貨機 (Context):這是我們的主要對象。
  • 狀態 (State):售貨機有多種狀態,比如:
    • 無幣狀態 (NoCoinState):沒有投幣。此時你按購買按鈕是無效的。
    • 有幣狀態 (HasCoinState):已經投幣。此時你可以選擇商品或退幣。
    • 售出商品狀態 (SoldState):正在出貨。此時你不能再投幣或選擇商品。
    • 商品售罄狀態 (SoldOutState):所有商品都賣完了。此時投幣會立即退回,選擇商品無效。

當用戶進行操作(如投幣、按按鈕)時,售貨機的行為會根據其當前狀態而有所不同。例如,在“無幣狀態”下投幣,售貨機會轉換到“有幣狀態”。在“有幣狀態”下按購買按鈕,如果商品充足,售貨機會轉換到“售出商品狀態”,然后(如果還有貨)可能回到“無幣狀態”。

狀態模式將每種狀態的行為封裝在不同的狀態對象中,Context 對象(售貨機)會將行為委托給當前的狀態對象。當 Context 的狀態改變時,它會切換到另一個狀態對象,從而改變其行為。

1. 目的 (Intent)

狀態模式的主要目的:

  1. 封裝與狀態相關的行為:將不同狀態下的行為邏輯分離到各自的狀態類中。
  2. 使狀態轉換明確:狀態轉換的邏輯可以分布在狀態類中,或者由 Context 統一管理。
  3. 避免大量的條件語句:如果不使用狀態模式,Context 類中可能會充斥著大量的 if/elseswitch 語句來根據當前狀態執行不同的行為。狀態模式通過多態性消除了這些條件分支。
  4. 使對象看起來像改變了類:當對象的狀態改變時,它的行為也隨之改變,給外部調用者的感覺就像是對象的類發生了變化。

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

  • 電燈開關

    • 狀態:開 (OnState),關 (OffState)。
    • 行為:按下開關。在“關”狀態下按,燈會亮,狀態變為“開”。在“開”狀態下按,燈會滅,狀態變為“關”。
  • TCP連接狀態

    • 狀態:已建立 (Established),監聽 (Listen),關閉 (Closed),正在關閉 (Closing) 等。
    • 行為:發送數據、接收數據、關閉連接等操作在不同狀態下有不同的表現或限制。
  • 播放器狀態

    • 狀態:播放中 (PlayingState),暫停 (PausedState),停止 (StoppedState)。
    • 行為:點擊播放/暫停按鈕,點擊停止按鈕。在不同狀態下,這些按鈕的行為不同。
  • 游戲角色的狀態

    • 狀態:站立、行走、跑步、跳躍、攻擊、防御、中毒、冰凍等。
    • 行為:玩家輸入指令(如移動、攻擊)時,角色的響應會根據其當前狀態而變化。

3. 結構 (Structure)

狀態模式通常包含以下角色:

  1. Context (上下文)

    • 定義客戶端感興趣的接口。
    • 維護一個 ConcreteState 子類的實例,這個實例定義當前狀態。
    • 可以將行為委托給當前的狀態對象。
    • 負責狀態的轉換,可以由 Context 自身或 State 對象來管理轉換邏輯。
  2. State (狀態接口或抽象類)

    • 定義一個接口以封裝與 Context 的一個特定狀態相關的行為。
    • 通常包含處理各種請求的方法,這些方法的實現在具體狀態類中。
  3. ConcreteState (具體狀態)

    • 實現 State 接口。
    • 每一個子類實現一個與 Context 的一種狀態相關的行為。
    • 可以負責狀態的轉換,即在執行完某個行為后,改變 Context 的當前狀態到下一個狀態。
      在這里插入圖片描述

狀態轉換的職責

  • 由 Context 決定:Context 接收到請求后,根據當前狀態和請求類型,決定轉換到哪個新狀態。
  • 由 State 子類決定:每個 ConcreteState 在處理完請求后,自行決定下一個狀態是什么,并通知 Context 改變狀態。這種方式更符合“狀態對象知道下一個狀態”的邏輯,但可能導致狀態類之間產生依賴。

4. 適用場景 (When to Use)

  • 一個對象的行為取決于它的狀態,并且它必須在運行時刻根據狀態改變它的行為。
  • 代碼中包含大量與對象狀態有關的條件語句(if/elseswitch)。狀態模式可以將這些分支邏輯分散到不同的狀態類中。
  • 當操作中含有龐大的多分支的條件語句,且這些分支依賴于該對象的狀態時。狀態模式將每一個分支封裝到一個獨立的類中。
  • 當你希望代碼更清晰地表達狀態和狀態轉換時。

5. 優缺點 (Pros and Cons)

優點:

  1. 封裝了與狀態相關的行為:將所有與特定狀態相關的行為都放入一個對象中,使得代碼更加集中和易于維護。
  2. 使得狀態轉換明確:將狀態轉換邏輯封裝在狀態類或 Context 中,使得狀態轉換的規則更加清晰。
  3. 消除了大量的條件分支:通過多態性替代了冗長的 if/elseswitch 語句,使代碼更簡潔,更易于理解和擴展。
  4. 易于增加新的狀態:增加新的狀態只需要添加一個新的 State 子類,并修改相關的轉換邏輯,符合開閉原則。

缺點:

  1. 類數量增多:狀態模式會導致系統中類的數量增加,每個狀態都需要一個對應的類。
  2. 結構可能變得復雜:如果狀態過多或者狀態轉換邏輯非常復雜,整個系統的結構可能會變得難以理解。
  3. Context 與 State 的耦合:State 對象通常需要訪問 Context 對象來改變其狀態或獲取 Context 的數據,這可能導致一定的耦合。如果 State 對象也負責狀態轉換,那么 State 對象之間也可能產生耦合。

6. 實現方式 (Implementations)

讓我們以一個簡單的文檔編輯器為例,它有草稿 (Draft)、審核中 (Moderation) 和已發布 (Published) 三種狀態。

狀態接口 (State)
// document_state.go (State interface and concrete states)
package state// Forward declaration for Document context
type Documenter interface {SetState(state Statelike)// Potentially other methods the state might need from the documentGetContent() stringSetContent(content string)
}// Statelike 狀態接口
type Statelike interface {Render(doc Documenter)Publish(doc Documenter)Review(doc Documenter) // New method for review processGetName() string
}
// State.java (State interface)
package com.example.state;public interface State {void render(Document document);void publish(Document document);void review(Document document); // New method for review processString getName();
}
具體狀態 (DraftState, ModerationState, PublishedState)
// document_state.go (continued)
package stateimport "fmt"// --- DraftState --- (草稿狀態)
type DraftState struct{}func NewDraftState() *DraftState { return &DraftState{} }func (s *DraftState) Render(doc Documenter) {fmt.Printf("Draft: Rendering content - '%s' (can be edited)\n", doc.GetContent())
}func (s *DraftState) Publish(doc Documenter) {fmt.Println("Draft: Content submitted for review.")doc.SetState(NewModerationState()) // Transition to Moderation
}func (s *DraftState) Review(doc Documenter) {fmt.Println("Draft: Cannot review a draft directly. Submit for review first.")
}func (s *DraftState) GetName() string { return "Draft" }// --- ModerationState --- (審核中狀態)
type ModerationState struct{}func NewModerationState() *ModerationState { return &ModerationState{} }func (s *ModerationState) Render(doc Documenter) {fmt.Printf("Moderation: Rendering content - '%s' (awaiting review, read-only)\n", doc.GetContent())
}func (s *ModerationState) Publish(doc Documenter) {fmt.Println("Moderation: Content approved and published.")doc.SetState(NewPublishedState()) // Transition to Published
}func (s *ModerationState) Review(doc Documenter) {// Simulate review logic, e.g., admin approves or rejects// For simplicity, let's assume it's always approved here by calling Publishfmt.Println("Moderation: Reviewing content...")s.Publish(doc) // If approved, it publishes// If rejected, it might go back to DraftState:// fmt.Println("Moderation: Content rejected, returning to draft.")// doc.SetState(NewDraftState())
}func (s *ModerationState) GetName() string { return "Moderation" }// --- PublishedState --- (已發布狀態)
type PublishedState struct{}func NewPublishedState() *PublishedState { return &PublishedState{} }func (s *PublishedState) Render(doc Documenter) {fmt.Printf("Published: Displaying content - '%s' (live, read-only)\n", doc.GetContent())
}func (s *PublishedState) Publish(doc Documenter) {fmt.Println("Published: Content is already published.")
}func (s *PublishedState) Review(doc Documenter) {fmt.Println("Published: Content is already published, no further review needed.")
}func (s *PublishedState) GetName() string { return "Published" }
// DraftState.java
package com.example.state;public class DraftState implements State {@Overridepublic void render(Document document) {System.out.println("Draft: Rendering content - '" + document.getContent() + "' (can be edited)");}@Overridepublic void publish(Document document) {System.out.println("Draft: Content submitted for review.");document.setState(new ModerationState()); // Transition to Moderation}@Overridepublic void review(Document document) {System.out.println("Draft: Cannot review a draft directly. Submit for review first.");}@Overridepublic String getName() {return "Draft";}
}// ModerationState.java
package com.example.state;public class ModerationState implements State {@Overridepublic void render(Document document) {System.out.println("Moderation: Rendering content - '" + document.getContent() + "' (awaiting review, read-only)");}@Overridepublic void publish(Document document) { // This is effectively 'approve and publish'System.out.println("Moderation: Content approved and published.");document.setState(new PublishedState()); // Transition to Published}@Overridepublic void review(Document document) {// In a real scenario, this might involve more complex logic or user roles.// For simplicity, let's say reviewing it means it's ready for publishing.System.out.println("Moderation: Reviewing content... Content looks good!");// If approved, it transitions to Published. This could be done here or by calling publish().// Let's assume the 'publish' action from Moderation state means 'approve and publish'.// If rejected, it might go back to DraftState:// System.out.println("Moderation: Content rejected, returning to draft.");// document.setState(new DraftState());// For this example, let's assume review leads to publish if called.this.publish(document); // Or a more specific 'approve' method that then calls publish.}@Overridepublic String getName() {return "Moderation";}
}// PublishedState.java
package com.example.state;public class PublishedState implements State {@Overridepublic void render(Document document) {System.out.println("Published: Displaying content - '" + document.getContent() + "' (live, read-only)");}@Overridepublic void publish(Document document) {System.out.println("Published: Content is already published.");}@Overridepublic void review(Document document) {System.out.println("Published: Content is already published, no further review needed.");}@Overridepublic String getName() {return "Published";}
}
上下文 (Document - Context)
// document.go (Context)
package context // Renamed package to avoid conflict with built-in contextimport ("../state""fmt"
)// Document 上下文
type Document struct {currentState state.Statelikecontent      string
}func NewDocument() *Document {doc := &Document{}doc.currentState = state.NewDraftState() // Initial statedoc.content = "Initial draft content."fmt.Printf("Document created. Initial state: %s\n", doc.currentState.GetName())return doc
}func (d *Document) SetState(s state.Statelike) {fmt.Printf("Document: Changing state from %s to %s\n", d.currentState.GetName(), s.GetName())d.currentState = s
}func (d *Document) GetContent() string {return d.content
}func (d *Document) SetContent(content string) {if d.currentState.GetName() == "Draft" { // Only allow content change in Draft stated.content = contentfmt.Printf("Document: Content updated to '%s'\n", content)} else {fmt.Printf("Document: Cannot set content in %s state.\n", d.currentState.GetName())}
}// Delegate actions to the current state
func (d *Document) Render() {d.currentState.Render(d)
}func (d *Document) Publish() {d.currentState.Publish(d)
}func (d *Document) Review() {d.currentState.Review(d)
}func (d *Document) GetCurrentStateName() string {return d.currentState.GetName()
}
// Document.java (Context)
package com.example.state;public class Document {private State currentState;private String content;public Document() {this.currentState = new DraftState(); // Initial statethis.content = "Initial draft content.";System.out.println("Document created. Initial state: " + currentState.getName());}public void setState(State state) {System.out.println("Document: Changing state from " + this.currentState.getName() + " to " + state.getName());this.currentState = state;}public String getContent() {return content;}public void setContent(String content) {// Example: Only allow content change in Draft stateif (this.currentState instanceof DraftState) {this.content = content;System.out.println("Document: Content updated to '" + content + "'");} else {System.out.println("Document: Cannot set content in " + this.currentState.getName() + " state.");}}// Delegate actions to the current statepublic void render() {this.currentState.render(this);}public void publish() {this.currentState.publish(this);}public void review() {this.currentState.review(this);}public String getCurrentStateName() {return this.currentState.getName();}
}
客戶端使用
// main.go (示例用法)
/*
package mainimport ("./context""fmt"
)func main() {doc := context.NewDocument()fmt.Println("\n--- Current State:" , doc.GetCurrentStateName(), "---")doc.Render() // Draft: Rendering content...doc.SetContent("My awesome first draft!")doc.Render()fmt.Println("\n--- Attempting to publish (from Draft) ---")doc.Publish() // Draft: Content submitted for review. (Transitions to Moderation)fmt.Println("\n--- Current State:" , doc.GetCurrentStateName(), "---")doc.Render() // Moderation: Rendering content...doc.SetContent("Trying to edit in moderation") // Cannot set contentdoc.Publish() // Moderation: Content approved and published. (Transitions to Published if publish means approve)// If publish from Moderation means 'request publish again', then it might stay or error.// In our example, ModerationState.publish() transitions to PublishedState.fmt.Println("\n--- Current State:" , doc.GetCurrentStateName(), "---")doc.Render() // Published: Displaying content...doc.Publish() // Published: Content is already published.// Let's try the review processfmt.Println("\n--- Resetting to a new document for review flow ---")doc2 := context.NewDocument()doc2.SetContent("Content for review process")doc2.Render()fmt.Println("\n--- Submitting for review (Publish from Draft) ---")doc2.Publish() // Transitions to Moderationfmt.Println("\n--- Current State:" , doc2.GetCurrentStateName(), "---")doc2.Render()fmt.Println("\n--- Reviewing the content (from Moderation) ---")doc2.Review() // Moderation: Reviewing content... Content approved and published. (Transitions to Published)fmt.Println("\n--- Current State:" , doc2.GetCurrentStateName(), "---")doc2.Render()
}
*/
// Main.java (示例用法)
/*
package com.example;import com.example.state.Document;public class Main {public static void main(String[] args) {Document doc = new Document();System.out.println("\n--- Current State: " + doc.getCurrentStateName() + " ---");doc.render(); // Draft: Rendering content...doc.setContent("My awesome first draft!");doc.render();System.out.println("\n--- Attempting to publish (from Draft) ---");doc.publish(); // Draft: Content submitted for review. (Transitions to Moderation)System.out.println("\n--- Current State: " + doc.getCurrentStateName() + " ---");doc.render(); // Moderation: Rendering content...doc.setContent("Trying to edit in moderation"); // Cannot set content// In our ModerationState, publish() means 'approve and publish'.// If we want a separate 'approve' action, we'd add an 'approve()' method to State and ConcreteStates.System.out.println("\n--- Attempting to publish/approve (from Moderation) ---");doc.publish(); // Moderation: Content approved and published. (Transitions to Published)System.out.println("\n--- Current State: " + doc.getCurrentStateName() + " ---");doc.render(); // Published: Displaying content...doc.publish(); // Published: Content is already published.// Let's try the review process more explicitlySystem.out.println("\n--- Resetting to a new document for review flow ---");Document doc2 = new Document();doc2.setContent("Content for review process");doc2.render();System.out.println("\n--- Submitting for review (Publish from Draft) ---");doc2.publish(); // Transitions to ModerationSystem.out.println("\n--- Current State: " + doc2.getCurrentStateName() + " ---");doc2.render();System.out.println("\n--- Reviewing the content (from Moderation) ---");doc2.review(); // Moderation: Reviewing content... Content approved and published. (Transitions to Published)System.out.println("\n--- Current State: " + doc2.getCurrentStateName() + " ---");doc2.render();}
}
*/

7. 狀態模式 vs. 策略模式 (State vs. Strategy)

狀態模式和策略模式在結構上非常相似(都依賴于組合和委托,將行為封裝在獨立的對象中),但它們的意圖不同:

  • 狀態模式 (State Pattern)

    • 意圖:允許一個對象在其內部狀態改變時改變它的行為。關注點是對象在不同狀態下的行為變化
    • 如何改變行為:Context 或 State 對象自身在運行時改變 Context 持有的 State 對象,從而改變行為。
    • 客戶端:客戶端通常不直接選擇狀態。狀態的改變是內部驅動的(基于操作的結果)或由 Context 自動管理的。
    • 生命周期:State 對象通常代表對象生命周期中的不同階段或條件。
  • 策略模式 (Strategy Pattern)

    • 意圖:定義一系列算法,將它們封裝起來,并使它們可以互相替換。關注點是提供多種算法選擇,并使它們可互換
    • 如何改變行為:客戶端在運行時選擇并向 Context 傳遞一個具體的 Strategy 對象。
    • 客戶端:客戶端通常知道有多種策略,并主動選擇一個策略來配置 Context。
    • 生命周期:Strategy 對象通常代表解決某個問題的不同方法或算法,與對象的內部狀態不一定直接關聯。

簡單來說

  • 狀態模式來表示“我是誰”(我的當前狀態決定了我的行為)。狀態轉換通常是預定義的,并且可能由對象內部事件觸發。
  • 策略模式來表示“我如何做”(我選擇哪種算法來完成任務)。策略通常由客戶端在外部設置。

在某些情況下,狀態對象本身也可以使用策略模式來處理其內部的某些行為變化,但這已經是模式的組合應用了。

8. 總結

狀態模式是一種強大的行為設計模式,它通過將與特定狀態相關的行為局部化,并將這些行為委托給代表當前狀態的對象,從而使得對象在內部狀態改變時能夠改變其行為。這不僅消除了大量的條件判斷語句,使得代碼更加清晰和易于維護,還使得添加新的狀態和轉換變得更加容易。當你發現一個對象的行為高度依賴于其內部狀態,并且這些狀態和轉換可以用清晰的界限劃分時,狀態模式會是一個非常好的選擇。

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

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

相關文章

面向對象面試題集合

前言 記錄面向對象面試題相關內容,方便復習及查漏補缺 題1.簡述面向對象?主要特征是什么? 面向對象編程(Object-Oriented Programming,簡稱OOP)是一種以“對象”為核心的編程范式,通過將現實…

二十一、【用戶管理與權限 - 篇三】角色管理:前端角色列表與 CRUD 實現

【用戶管理與權限 - 篇三】角色管理:前端角色列表與 CRUD 實現 前言準備工作第一部分:更新 API 服務以包含角色管理第二部分:添加角色管理頁面的路由和側邊欄入口第三部分:實現角色列表頁面第四部分:實現角色表單對話框組件第五部分:全面測試總結前言 一個完善的權限系統…

Objective-c protocol 練習

題目描述: 請使用 Objective-C 中的 protocol 協議機制,實現一個簡易的門禁控制系統。 系統包含兩個類: AccessControlSystem —— 門禁系統,用于執行開門操作;Admin —— 實現權限判斷邏輯的管理員。 要求如下&am…

科技創新賦能產業創新,雙輪驅動助力新疆高質量發展!

在新疆維吾爾自治區成立70周年之際,中國產學研合作促進會于6月14日在烏魯木齊舉辦“天山對話:推動新疆科技創新與產業創新”盛會。多位院士、專家、學者及企業代表齊聚一堂,探尋推動新疆科技創新和產業創新的新路徑、新動能。活動現場&#x…

C#最佳實踐:推薦使用 nameof 而非硬編碼名稱

C#最佳實踐:推薦使用 nameof 而非硬編碼名稱 在 C# 編程領域,代碼的可維護性、健壯性和可讀性是衡量程序質量的重要指標。在日常開發中,我們常常會遇到需要引用類型、成員或變量名稱的場景,比如在拋出異常時指定錯誤相關的變量名、在日志記錄中標記關鍵元素名稱等。傳統的…

vue3 iframe 跨域-通訊

一、基礎嵌套方法 直接在 HTML 中使用 <iframe> 標簽指定 src 屬性&#xff1a; <iframe src"https://目標網址.com" width"800" height"600"></iframe>?限制?&#xff1a;若目標網站設置了 X-Frame-Options 響應頭&#x…

Iceberg與Hive集成深度

一、Iceberg在Hive中的ACID事務實現與實戰 1.1 傳統Hive的事務局限性 Hive原生僅支持非事務表&#xff08;Non-ACID&#xff09;&#xff0c;存在以下痛點&#xff1a; 不支持行級更新/刪除并發寫入時數據一致性無法保證無事務回滾機制歷史版本查詢需手動實現 1.2 Iceberg為…

深入剖析 Celery:分布式異步任務處理的利器

本文在創作過程中借助 AI 工具輔助資料整理與內容優化。圖片來源網絡。 文章目錄 引言一、Celery 概述1.1 Celery 的定義和作用1.2 Celery 的應用場景 二、Celery 架構分析2.1 Celery 的整體架構2.2 消息中間件&#xff08;Broker&#xff09;2.3 任務隊列&#xff08;Task Que…

Flask應用中處理異步事件(后臺線程+事件循環)的方法(2)

在上一節&#xff0c;我們講述了最簡單最基礎的后線程的建立&#xff0c;現在我們將進行拓展 Flask應用中處理異步事件&#xff08;后臺線程事件循環&#xff09;的方法&#xff08;1&#xff09; 在我們的實際應用當中&#xff0c;我們需要定義三個東西 一個多線程的信號旗&am…

C++(面向對象編程)

思維導圖 面向對象 1.面向對象思想 概念&#xff1a;面向對象編程&#xff08;OOP&#xff09;是一種以對象為基礎的編程范式&#xff0c;強調將數據和操作數據的方法封裝在一起。這就是上篇文章講過的。面向過程是以“怎么解決問題”為核心&#xff0c;而面向對象思想在于“誰…

驅動程序無法通過使用安全套接字層(SSL)加密與 SQL Server 建立安全連接,

驅動程序無法通過使用安全套接字層(SSL)加密與 SQL Server 建立安全連接,Error: “The server selected protocol version TLS10 is not accepted by client preferences [TLS13&#xff0c;TLS12]”. ClientConnectionId:d5fd8d69-ae88-4055-9f6d-6e8515224ce2】。 基本上就是…

【三大前端語言之一】交互:JavaScript詳解

【三大前端語言之一】交互&#xff1a;JavaScript詳解 在學習完HTML和CSS之后&#xff0c;最后一門前端語言——JavaScript&#xff0c;是重中之重。HTML負責頁面結構&#xff0c;CSS負責頁面樣式&#xff0c;而JavaScript則賦予網頁“生命”&#xff0c;讓網頁可以動起來、響…

LangChain面試內容整理-知識點12:檢索器(Retriever)接口與實現

在LangChain中,檢索器(Retriever)是一個抽象接口,負責根據用戶查詢從數據源中檢索相關文檔。可以把Retriever理解為“搜索工具”:給它一個未經結構化的查詢文本(如用戶問題),它返回一組與之相關的 Document 對象。內部可以基于向量相似度、數據庫查詢、甚至網絡搜索。 …

LLVM前端和優化層

文章目錄 LLVM ArchitectueLLVM 前端Lexical Analysis詞法分析Syntactic analysis 語法分析Syntactic Analyze語義分析 LLVM 優化層Pass 基礎概念Pass 依賴關系Pass API 總結 LLVM Architectue LLVM 前端 LLVM 的前端其實是把源代碼也就是 C、C、Python 這些高級語言變為編譯器…

工作流和Agent 的區別與聯系

工作流和智能體可能讓人混淆的地方就是他們都可能有大模型的加持&#xff0c;都可能有工具的加入供大模型調用&#xff0c;本文做一下對比和聯系 工作流 (Workflow) 定義&#xff1a; 工作流是一系列預定義、結構化且可重復的步驟或任務&#xff0c;旨在完成特定的業務目標或解…

leetcode--用StringBulider反轉字符串單詞的巧妙解法

反轉字符串中的單詞 這道題理想中的操作方式就是先去除前導和尾隨空格&#xff0c;之后設一個尾指針&#xff0c;往前檢索&#xff0c;掃到一個單詞就把這個單詞放到字符串的第一個位置。 很明顯&#xff0c;java中我們不能直接對字符串進行修改&#xff0c;而我們想實現一個一…

連鎖零售行業智慧能源管理解決方案:精準管控,讓每一度電創造價值

在連鎖超市、便利店等業態中&#xff0c;門店分布廣、用能場景復雜、管理成本高是普遍難題。傳統能源管理模式依賴人工抄表與分散管理&#xff0c;存在數據滯后、響應效率低、安全隱患難排查等問題。以某全國幾千家門店的連鎖便利店為例&#xff0c;其面臨的挑戰包括&#xff1…

在 PostgreSQL 中實現 `lck`, `special`, `item` 與 `org_id` 或 `user_id` 組合唯一的約束

在 PostgreSQL 中實現 lck, special, item 與 org_id 或 user_id 組合唯一的約束 要實現 lck, special, item 這三個字段必須與 org_id 或 user_id 中的一個&#xff08;但不能同時&#xff09;組合唯一的約束&#xff0c;你需要創建以下約束&#xff1a; 方案1&#xff1a;使…

g++ a.cpp -o a ‘pkg-config --cflags --libs opencv4‘/usr/bin/ld: 找不到 沒有那個文件或目錄

這個錯誤表明 pkg-config 命令沒有正確執行&#xff0c;導致編譯器無法找到 OpenCV 的庫文件和頭文件路徑。pkg-config 是一個工具&#xff0c;用于查詢已安裝庫的編譯和鏈接選項。如果 pkg-config 無法找到 OpenCV 的配置文件&#xff0c;就會導致這個錯誤。 以下是解決這個問…

定制平板在智能家居中能做些什么?全面解析其核心功能

大家有沒有發現&#xff0c;現在智能家居越來越普及了&#xff0c;很多家庭都在逐步升級自己的居住體驗。而在這一過程中&#xff0c;一種設備正悄悄地取代我們以前常用的開關面板和手機APP&#xff0c;成為整個家庭智能控制的核心&#xff0c;這就是——定制平板。 它可不是我…