您在開發過程中是否遇到需要處理複雜物件的情況?可能是因為它們要么參數太多,甚至可以嵌套,要么需要很多構建步驟和複雜的邏輯來構建。
也許您想設計一個具有簡潔介面的模組,而不必每次都分散或思考複雜物件的創建程式碼!
這就是建構器設計模式的用武之地!
在本教程中,我們將解釋有關構建器設計模式的所有內容,然後我們將構建一個CLI Node.js 應用程序,用於使用構建器設計模式 生成DALL-E 3優化的影像產生提示.
最終程式碼可在此 Github 儲存庫中取得。
Builder 是一種創造設計模式,它是一類設計模式,用於處理使用new 創建物件的本機方式所帶來的不同問題。 關鍵字或運算子。
建構器設計模式專注於解決以下問題:
提供一個簡單的介面來創建複雜的對象:想像一個深度嵌套的對象,它具有許多必需的初始化步驟。
將建構程式碼與物件本身分開,允許從同一物件建立多個表示或配置。
Builder 設計模式 透過將物件建立的責任委託給稱為 builders 的特殊物件來解決這兩個問題。
建構器物件組合原始對象,並將建立過程分解為多個階段或步驟。
每個步驟都由建構器物件中的一個方法定義,該方法根據某些業務邏輯初始化物件屬性的子集。
class PromptBuilder { private prompt: Prompt constructor() { this.reset() } reset() { this.prompt = new Prompt() } buildStep1() { this.prompt.subject = "A cheese eating a burger" //initialization code... return this } buildStep2() { //initialization code... return this } buildStep3() { //initialization code... return this } build() { const result = structuredClone(this.prompt) // deep clone this.reset() return result } }
客戶端程式碼:我們只需要使用建構器並呼叫各個步驟
const promptBuilder = new PromptBuilder() const prompt1 = promptBuilder .buildStep1() // optional .buildStep2() // optional .buildStep3() // optional .build() // we've got a prompt const prompt2 = promptBuilder .buildStep1() // optional .buildStep3() // optional .build() // we've got a prompt
典型的建構器設計模式由 4 個主要類別組成:
Builder :建構器介面應該只定義建構方法,而沒有 build() 方法,該方法負責傳回已建立的實體。
具體建構器類別:每個特定建構器都提供自己的建構器介面方法的實現,以便它可以產生自己的物件變體(產品1或產品2)。
客戶端 :您可以將客戶端視為我們物件的頂級消費者、匯入庫模組的使用者或我們應用程式的入口點。
Director:即使同一個構建器物件也可以產生該物件的許多變體。
class PromptBuilder { private prompt: Prompt constructor() { this.reset() } reset() { this.prompt = new Prompt() } buildStep1() { this.prompt.subject = "A cheese eating a burger" //initialization code... return this } buildStep2() { //initialization code... return this } buildStep3() { //initialization code... return this } build() { const result = structuredClone(this.prompt) // deep clone this.reset() return result } }從上面的程式碼可以看出,某些實體非常需要負責指導或編排對建構器方法的不同可能的呼叫組合序列,因為每個序列可能會產生不同的結果物件。
那麼我們能否進一步抽象流程,為客戶端程式碼提供更簡單的介面?
這就是
Director 類別 的用武之地。 director 從客戶端承擔更多責任,並允許我們分解所有這些建構器序列呼叫並根據需要重複使用它們。
const promptBuilder = new PromptBuilder() const prompt1 = promptBuilder .buildStep1() // optional .buildStep2() // optional .buildStep3() // optional .build() // we've got a prompt const prompt2 = promptBuilder .buildStep1() // optional .buildStep3() // optional .build() // we've got a prompt
客戶端程式碼
const promptBuilder = new PromptBuilder() const prompt1 = promptBuilder.buildStep1().buildStep2().build() const prompt2 = promptBuilder.buildStep1().buildStep3().build()從上面的程式碼可以看出,客戶端程式碼不需要知道建立prompt1或prompt2的詳細資料。它只是呼叫主管,設定正確的建構器對象,然後呼叫 makePrompt 方法。
實際場景
快速工程影像產生AI CLI工具。
此 CLI 應用程式的原始程式碼可在此處取得。CLI 工具的工作方式如下:
檔案:promps.ts
class Director { private builder: PromptBuilder constructor() {} setBuilder(builder: PromptBuilder) { this.builder = builder } makePrompt1() { return this.builder.buildStep1().buildStep2().build() } makePrompt2() { return this.builder.buildStep1().buildStep3().build() } }
檔案:promps.ts
const director = new Director() const builder = new PromptBuilder() director.setBuilder(builder) const prompt1 = director.makePrompt1() const prompt2 = director.makePrompt2()如您所見,每種提示類型都需要建立許多複雜的屬性,例如
artStyle 、 colorPalette 、 lightingEffect 、 perspective 、 相機種類 等
隨意探索所有屬性詳細信息,這些詳細信息在我們項目的enums.ts 文件中定義。
枚舉.ts
class PromptBuilder { private prompt: Prompt constructor() { this.reset() } reset() { this.prompt = new Prompt() } buildStep1() { this.prompt.subject = "A cheese eating a burger" //initialization code... return this } buildStep2() { //initialization code... return this } buildStep3() { //initialization code... return this } build() { const result = structuredClone(this.prompt) // deep clone this.reset() return result } }
我們的CLI 應用程式的用戶可能不知道所有這些配置;他們可能只想根據特定的主題生成圖像,例如吃起司漢堡和風格(現實或數字藝術)。
複製 Github 儲存庫後,使用以下指令安裝依賴項:
const promptBuilder = new PromptBuilder() const prompt1 = promptBuilder .buildStep1() // optional .buildStep2() // optional .buildStep3() // optional .build() // we've got a prompt const prompt2 = promptBuilder .buildStep1() // optional .buildStep3() // optional .build() // we've got a prompt
安裝依賴項後,執行以下命令:
const promptBuilder = new PromptBuilder() const prompt1 = promptBuilder.buildStep1().buildStep2().build() const prompt2 = promptBuilder.buildStep1().buildStep3().build()
系統將提示您選擇提示類型:現實或數位藝術。
然後您必須輸入提示的主題。讓我們堅持起司漢堡。
根據您的選擇,您將收到以下文字提示:
寫實風格提示 :
class Director { private builder: PromptBuilder constructor() {} setBuilder(builder: PromptBuilder) { this.builder = builder } makePrompt1() { return this.builder.buildStep1().buildStep2().build() } makePrompt2() { return this.builder.buildStep1().buildStep3().build() } }
數位藝術風格提示 :
const director = new Director() const builder = new PromptBuilder() director.setBuilder(builder) const prompt1 = director.makePrompt1() const prompt2 = director.makePrompt2()
複製先前的命令,然後將其貼上到 ChatGPT 中。 ChatGPT 將使用 DALL-E 3 模型來產生影像。
真實影像提示結果
數位藝術影像提示結果
記住提示參數的複雜性以及建立每種類型的提示所需的專業知識,更不用說所需的醜陋的建構函式呼叫。
class RealisticPhotoPrompt { constructor( public subject: string, public location: string, public timeOfDay: string, public weather: string, public camera: CameraType, public lens: LensType, public focalLength: number, public aperture: string, public iso: number, public shutterSpeed: string, public lighting: LightingCondition, public composition: CompositionRule, public perspective: string, public foregroundElements: string[], public backgroundElements: string[], public colorScheme: ColorScheme, public resolution: ImageResolution, public postProcessing: string[] ) {} }
免責宣告:這個醜陋的建構函式呼叫在 JavaScript 中並不是一個大問題,因為我們可以傳遞一個所有屬性都可為空的配置物件。
抽象構建提示的過程,並使我們的程式碼開放擴展並關閉修改(O in SOLID),並讓我們的圖書館客戶無縫或更輕鬆地使用我們的提示生成庫,我們將選擇實作建構器設計模式。
讓我們先聲明通用提示產生器介面。
介面宣告了一堆方法:
builders.ts
class PromptBuilder { private prompt: Prompt constructor() { this.reset() } reset() { this.prompt = new Prompt() } buildStep1() { this.prompt.subject = "A cheese eating a burger" //initialization code... return this } buildStep2() { //initialization code... return this } buildStep3() { //initialization code... return this } build() { const result = structuredClone(this.prompt) // deep clone this.reset() return result } }
builders.ts
const promptBuilder = new PromptBuilder() const prompt1 = promptBuilder .buildStep1() // optional .buildStep2() // optional .buildStep3() // optional .build() // we've got a prompt const prompt2 = promptBuilder .buildStep1() // optional .buildStep3() // optional .build() // we've got a prompt
從上面的實作中可以看到,每個建構器都選擇建立自己類型的提示(最終的提示形狀不同),同時堅持 PromptBuilder 合約定義的相同建置步驟!
現在,讓我們繼續我們的 Director 類別定義。
導演.ts
const promptBuilder = new PromptBuilder() const prompt1 = promptBuilder.buildStep1().buildStep2().build() const prompt2 = promptBuilder.buildStep1().buildStep3().build()
Director 類別包裝了PromptBuilder 並允許我們建立一個提示配置,其中包括呼叫從setSubject 到 的所有建構器方法Element 🎜>.
這將簡化index.ts 文件中的客戶端程式碼,我們將在下一節中看到。
序列化器.ts
class Director { private builder: PromptBuilder constructor() {} setBuilder(builder: PromptBuilder) { this.builder = builder } makePrompt1() { return this.builder.buildStep1().buildStep2().build() } makePrompt2() { return this.builder.buildStep1().buildStep3().build() } }為了將最終提示文字列印到終端控制台,我實作了一些實用程式序列化函數。
現在我們的提示庫產生程式碼已經準備好了。讓我們在
index.ts 檔案中使用它。
index.ts
const director = new Director() const builder = new PromptBuilder() director.setBuilder(builder) const prompt1 = director.makePrompt1() const prompt2 = director.makePrompt2()上面的程式碼執行以下操作:
請記住:不可能從導演那裡獲得提示,因為每種建構器類型產生的提示形狀不同。結論
簡化物件建立:此模式可讓我們建立複雜的 RealisticPhotoPrompt 和 DigitalArtPrompt 對象,而無需將其複雜的建構流程暴露給客戶端程式碼。
靈活性:透過為每種提示類型使用單獨的建構器類,我們可以輕鬆添加新的提示類型或修改現有的提示類型,而無需更改客戶端程式碼。
程式碼組織:此模式有助於將建構邏輯與表示分離,使程式碼更加模組化且更易於維護。
可重用性:PromptDirector 類別允許我們為不同類型的提示重用相同的建構過程,增強程式碼的可重用性。
抽象 :index.ts 中的客戶端程式碼保持簡單並專注於高階邏輯,而提示建構的複雜性在建構器類別中被抽象化。
如果您有任何疑問或想進一步討論,請隨時與我聯絡。
編碼愉快!
以上是掌握建構器模式:建立動態 AI 提示產生器 CLI的詳細內容。更多資訊請關注PHP中文網其他相關文章!