设计模式(2) 生成器模式(BUILDER)
生活随笔
收集整理的這篇文章主要介紹了
设计模式(2) 生成器模式(BUILDER)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
問題聚焦:
? ? ? ? 生成器模式是對象創建型模式的一種
? ? ? ? 它將一個復雜的對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
意圖: 正如上面所說,生成器的意圖是將一個復雜的對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
動機:以一個例子解釋生成器的動機
Demo: 一個具有格式轉換供功能的閱讀器應該能將原始的RTF格式轉換為多種正文格式。目的格式的種類可以任意類型的,因此要求是要很容易地實現新的轉換的增加,同時不改變RTF閱讀器。 解決辦法:步驟使用一個輔助類,來配置這個類(比如是RTFReader),這個輔助類(比如是TextConverter類)可以將原始的RTF格式轉換成另一種格式的文本表示; RTFReader類(又稱為導向器)專注于對文檔的詞法分析,而將每個單詞或者符號的轉換交給TextConverter; TextConverter對象(稱為生成器)負責對數據進行轉換以及用特定格式表示該標記; TextConvert的子類對不同轉換和不同格式進行特殊處理。
目的:重用RTFReader的詞法分析算法,根據目的格式的不同,使用不同的TextConverter的子類配置該RTFReader。
設計:
適用性: 在以下情況使用Buider模式
參與者:
依然以創建迷宮為例: 這里我們定義一個CreateMaze成員函數的變體,它以類MazeBuilder的一個生成器對象作為參數。 MazeBuilder類定義如下 class MazeBuilder { public:virtual void BuildMaze() {}virtual void BuildRoom(int room) {}virtual void BuildDoor(int roomFrom, int roomTo) {}virtual Maze* GetMaze() { return 0;} protected:MazeBuilder(); }
以生成器為參數的CreateMaze成員函數版本 Maze* MazeGame::CreateMaze (MazeBuilder& builder) {builder.BuildMaze();builder.BuildRoom(1);builder.BuildRoom(2);builder.BuildDoor(1,2);return builder.GetMaze(); }
關于生成器的子類對具體的迷宮的實現的代碼這里不再貼出,下面演示一下怎樣使用一個生成器子類CountingMazeBuilder int rooms, doors; MazeGame game; CountingMazeBuilder builder;game.CreateMaze(builder); builder.getCounts(rooms, doors);
相關模式 抽象工廠和生成器模式的比較: 共同點:都可以創建復雜對象 區別: Builder模式著重一步步構造一個復雜對象,這個產品可能在導向器和生成器之間傳遞很多次,最后返回產品 抽象工廠著重于產品的多個系列,而且產品是在工廠中一次加工好然后返回的,并沒有出現產品的半成品返廠的情況出現(這點可以將兩個模式的示例代碼比較一下,就會有感觸)
參考資料: 《設計模式》
意圖: 正如上面所說,生成器的意圖是將一個復雜的對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
動機:以一個例子解釋生成器的動機
Demo: 一個具有格式轉換供功能的閱讀器應該能將原始的RTF格式轉換為多種正文格式。目的格式的種類可以任意類型的,因此要求是要很容易地實現新的轉換的增加,同時不改變RTF閱讀器。 解決辦法:步驟
適用性: 在以下情況使用Buider模式
- 當創建復雜對象的算法應該獨立于該對象的組成部分以及它們的裝配方式時
- 當構造過程必須允許被構造的對象有不同的表示時
參與者:
- Builder(TextConverter):為創建一個Product對象的各個部件指定抽象接口
- ConcreteBuilder(ASCIIConverter、TeXConverter、TextWidgetConverter) : ? 實現Builder的接口以及構造和裝配該產品的各個部件; 定義并明確它所創建的表示; 提供一個檢索產品的接口
- Director(RTFReader):構造一個使用Builder接口的對象
- Product(ASCIIText、TeXText、TextWidget):表示被構建的復雜對象,包含定義組成部件的類,包括將這些部件裝配成最終產品的接口
- 客戶創建Director對象,并用他想要的Builder對象進行配置
- 一旦產品部件被生成,導向器就會通知生成器
- 生成器處理導向器的請求,并將部件添加到該產品中
- 客戶從生成器中檢索產品
- 它使你可以改變一個產品的內部表示:Buidler對象給使用它的導向器提供一個抽象接口,產品是通過這個抽象接口構造的,你在生產一個新的產品時需要定義一個新的生成器
- 它將構造代碼和表示代碼分開:Builder模式通過封裝一個復雜對象的創建和表示方式提高了對象的模塊性
- 它使你可對構造過程進行更精細的控制:Builder模式與一下子就生成產品的創建型模式不同,它是在導向者的控制下一步一步構造產品。因此可以更好地反映產品的構造過程。
- 裝配和構造接口:生成器逐步地構造它們的產品,因此Builder類接口必須足夠普遍,以便為各種類型的具體生成器構造產品;
- 產品沒有抽象類:各個產品相差很大,所以并沒有必要定義一個抽象類繼承它;
- 在Builder中缺省的方法為空:C++中,各個構建的生成方法故意不聲明為純虛成員函數,而是把它們是定義為空方法,這使客戶只重定義他們所感興趣的操作。
依然以創建迷宮為例: 這里我們定義一個CreateMaze成員函數的變體,它以類MazeBuilder的一個生成器對象作為參數。 MazeBuilder類定義如下 class MazeBuilder { public:virtual void BuildMaze() {}virtual void BuildRoom(int room) {}virtual void BuildDoor(int roomFrom, int roomTo) {}virtual Maze* GetMaze() { return 0;} protected:MazeBuilder(); }
以生成器為參數的CreateMaze成員函數版本 Maze* MazeGame::CreateMaze (MazeBuilder& builder) {builder.BuildMaze();builder.BuildRoom(1);builder.BuildRoom(2);builder.BuildDoor(1,2);return builder.GetMaze(); }
關于生成器的子類對具體的迷宮的實現的代碼這里不再貼出,下面演示一下怎樣使用一個生成器子類CountingMazeBuilder int rooms, doors; MazeGame game; CountingMazeBuilder builder;game.CreateMaze(builder); builder.getCounts(rooms, doors);
相關模式 抽象工廠和生成器模式的比較: 共同點:都可以創建復雜對象 區別: Builder模式著重一步步構造一個復雜對象,這個產品可能在導向器和生成器之間傳遞很多次,最后返回產品 抽象工廠著重于產品的多個系列,而且產品是在工廠中一次加工好然后返回的,并沒有出現產品的半成品返廠的情況出現(這點可以將兩個模式的示例代碼比較一下,就會有感觸)
參考資料: 《設計模式》
總結
以上是生活随笔為你收集整理的设计模式(2) 生成器模式(BUILDER)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我的世界服务器无限箱子指令,我的世界功能
- 下一篇: 24种设计模式-生成器模式