設計模式——建造者(Builder)模式

建造者模式(Builder Pattern),又叫生成器模式,是一種對象構建模式 它可以將復雜對象的建造過程抽象出來,使這個抽象過程的不同實現方法可以構造出不同表現的對象。建造者模式是一步一步創建一個復雜的對象,它允許用戶只通過指定復雜對象的類型和內容就可 以構建它們,用戶不需要知道內部的具體構建細節。

簡單來說,建造者模式允許你按步驟創建復雜的對象,同時將對象的構建與其表示分離。

主要解決的問題是當創建一個復雜對象時,如果直接在代碼中進行對象的創建和初始化,會導致代碼變得復雜而難以維護。

而建造者模式通過將對象的構建過程委派給不同的建造者,使得代碼更加清晰、可讀,并且可以靈活地構建不同的對象表示形式。

當我們需要創建一個對象,但該對象具有復雜的構建過程,并且構建過程可以有不同的表示形式時,可以考慮使用建造者模式。

建造者模式包含4個元素:

  • 抽象建造者(Builder):一個抽象接口,規范了產品對象的各個組成成分的建造。
  • 具體建造者(ConcreteBuilder):與應用程序緊密相關的一些類,它們在應用程序調用下創建產品的實例。
  • 導演者(Director):調用具體建造者角色來創建產品對象。
  • 產品(Product):一般是一個較為復雜的對象。

優點包括:

  1. 將對象的構建過程封裝在一個建造者類中,使得客戶端代碼與具體構建過程解耦,提高了代碼的可維護性和可讀性。
  2. 可以靈活地構建不同表示形式的對象,通過調整建造者的步驟和配置,可以得到不同的對象。
  3. 可以更好地控制對象的構建過程,避免了在代碼中直接創建和初始化對象的復雜性。

缺點包括:

  1. 建造者模式增加了代碼的復雜性,因為需要定義多個類來實現構建者和產品對象,可能會增加項目的工程復雜性。
  2. 如果產品的屬性發生變化,需要修改構建者類和產品類,可能會引起一定的維護成本。

注意事項:與工廠模式的區別是:建造者模式更加關注與零件裝配的順序。

案例

我們假設一個快餐店的商業案例,其中,一個典型的套餐可以是一個漢堡(Burger)和一杯冷飲(Cold drink)。漢堡(Burger)可以是素食漢堡(Veg Burger)或雞肉漢堡(Chicken Burger),它們是包在紙盒中。冷飲(Cold drink)可以是可口可樂(coke)或百事可樂(pepsi),它們是裝在瓶子中。

我們將創建一個表示食物條目(比如漢堡和冷飲)的 Item 接口和實現 Item 接口的實體類,以及一個表示食物包裝的 Packing 接口和實現 Packing 接口的實體類,漢堡是包在紙盒中,冷飲是裝在瓶子中。

然后我們創建一個 Meal 類,帶有 ItemArrayList 和一個通過結合 Item 來創建不同類型的 Meal 對象的 MealBuilderBuilderPatternDemo 類使用 MealBuilder 來創建一個 Meal

建造者模式的 UML 圖

步驟 1

創建一個表示食物條目和食物包裝的接口。

public interface Item {public String name();public Packing packing();public float price();    
}

public interface Packing {public String pack();
}

步驟 2

創建實現 Packing 接口的實體類。

public class Wrapper implements Packing {@Overridepublic String pack() {return "Wrapper";}
}
public class Bottle implements Packing {@Overridepublic String pack() {return "Bottle";}
}

步驟 3

創建實現 Item 接口的抽象類,該類提供了默認的功能。

public abstract class Burger implements Item {@Overridepublic Packing packing() {return new Wrapper();}@Overridepublic abstract float price();
}
public abstract class ColdDrink implements Item {@Overridepublic Packing packing() {return new Bottle();}@Overridepublic abstract float price();
}

步驟 4

創建擴展了 Burger 和 ColdDrink 的實體類。

public class VegBurger extends Burger {@Overridepublic float price() {return 25.0f;}@Overridepublic String name() {return "Veg Burger";}
}
public class ChickenBurger extends Burger {@Overridepublic float price() {return 50.5f;}@Overridepublic String name() {return "Chicken Burger";}
}
public class Coke extends ColdDrink {@Overridepublic float price() {return 30.0f;}@Overridepublic String name() {return "Coke";}
}
public class Pepsi extends ColdDrink {@Overridepublic float price() {return 35.0f;}@Overridepublic String name() {return "Pepsi";}
}

步驟 5

創建一個 Meal 類,帶有上面定義的 Item 對象。

import java.util.ArrayList;
import java.util.List;public class Meal {private List<Item> items = new ArrayList<Item>();    public void addItem(Item item){items.add(item);}public float getCost(){float cost = 0.0f;for (Item item : items) {cost += item.price();}        return cost;}public void showItems(){for (Item item : items) {System.out.print("Item : "+item.name());System.out.print(", Packing : "+item.packing().pack());System.out.println(", Price : "+item.price());}        }    
}

步驟 6

創建一個 MealBuilder 類,實際的 builder 類負責創建 Meal 對象。

public class MealBuilder {public Meal prepareVegMeal (){Meal meal = new Meal();meal.addItem(new VegBurger());meal.addItem(new Coke());return meal;}   public Meal prepareNonVegMeal (){Meal meal = new Meal();meal.addItem(new ChickenBurger());meal.addItem(new Pepsi());return meal;}
}

步驟 7

BuiderPatternDemo 使用 MealBuilder 來演示建造者模式(Builder Pattern)。

public class BuilderPatternDemo {public static void main(String[] args) {MealBuilder mealBuilder = new MealBuilder();Meal vegMeal = mealBuilder.prepareVegMeal();System.out.println("Veg Meal");vegMeal.showItems();System.out.println("Total Cost: " +vegMeal.getCost());Meal nonVegMeal = mealBuilder.prepareNonVegMeal();System.out.println("\n\nNon-Veg Meal");nonVegMeal.showItems();System.out.println("Total Cost: " +nonVegMeal.getCost());}
}

步驟 8

執行程序,輸出結果:

Veg Meal
Item : Veg Burger, Packing : Wrapper, Price : 25.0
Item : Coke, Packing : Bottle, Price : 30.0
Total Cost: 55.0Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5

總結

建造者模式是一種創建型設計模式,用于將復雜對象的構建過程與其表示分離。它通過將復雜對象的構建過程分解為多個簡單的步驟來實現。在Java中,我們可以使用建造者模式來創建復雜對象,并且可以根據需要使用不同的建造者來創建不同的表示。建造者模式的優點包括可重用性和易于維護和擴展,但它的缺點是代碼結構較為復雜。建造者模式適用于需要創建多個相似對象,或者需要在不同的上下文中創建不同的對象表示的情況。如果需要創建的對象較為簡單,可能會使用建造者模式變得過于繁瑣。

總之,建造者模式是一種非常有用的設計模式,可以幫助我們更好地管理對象的構建過程,并且使得代碼更加易于維護和擴展。如果你需要創建一個復雜的對象,或者需要在不同的上下文中創建不同的對象表示,建議你考慮使用建造者模式來實現。

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

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

相關文章

(14)嵌套列表,Xpath路徑表達式,XML增刪查改,Implicit,Operator,Xml序列化,淺拷貝與深拷貝

一、作業問題 1、問&#xff1a;listbox1.items[i]返回的object是指的字符串嗎&#xff1f; 答&#xff1a;items是真正的對象集合&#xff0c;在Add時加的是Person對象p&#xff0c;則里面的item就是Person對象p。 但是&#xff0c;在listbox1顯…

在單元測試中使用Jest模擬VS Code extension API

對VS Code extension進行單元測試時通常會遇到一個問題&#xff0c;代碼中所使用的VS Code編輯器的功能都依賴于vscode庫&#xff0c;但是我們在單元測試中并沒有添加對vscode庫的依賴&#xff0c;所以導致運行單元測試時出錯。由于vscode庫是作為第三方依賴被引入到我們的VS C…

[oneAPI] BERT

[oneAPI] BERT BERT訓練過程Masked Language Model&#xff08;MLM&#xff09;Next Sentence Prediction&#xff08;NSP&#xff09;微調 總結基于oneAPI代碼 比賽&#xff1a;https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517 Intel DevCloud for oneAPI&…

JVM 中的編譯器

在Java的世界里,JVM(Java Virtual Machine)扮演了重要的角色。JVM是一個虛擬機,是Java程序的運行環境,它能夠將Java字節碼文件解釋執行,使得Java程序可以跨平臺。在JVM內部,有一個重要的組件就是編譯器,它的作用就是將Java源代碼編譯成字節碼,讓JVM可以識別并執行。 …

redis集群和分片-Redis Cluster:分布式環境中的數據分片、主從復制和 Sentinel 哨兵

當涉及到 Redis 中的集群、分片、主從復制和 Sentinel 哨兵時&#xff0c;這些是構建分布式 Redis 環境中非常重要的概念和組件。下面詳細介紹這些概念以及它們在分布式環境中的作用。 Redis Cluster Redis Cluster 是 Redis 官方提供的分布式解決方案&#xff0c;用于管理和…

React源碼解析18(4)------ completeWork的工作流程【mount】

摘要 經過上一章&#xff0c;我們得到的FilberNode已經具有了child和return屬性。一顆Filber樹的結構已經展現出來了。 那我們最終是想在頁面渲染真實的DOM。所以我們現在要在completeWork里&#xff0c;構建出一顆離屏的DOM樹。 之前在說FilberNode的屬性時&#xff0c;我們…

zabbix案例--zabbix監控Tomcat

目錄 一、 部署tomcat 二、配置zabbix-java-gateway 三、配置zabbix-server 四、配置zabbix-web界面 一、 部署tomcat tar xf apache-tomcat-8.5.16.tar.gz -C /usr/local/ ln -sv /usr/local/apache-tomcat-8.5.16/ /usr/local/tomcat cd /usr/local/tomcat/bin開啟JMX…

Vscode 常用操作教程

一、語言換成中文 這是我們可以直接點擊左邊欄第四個圖標搜索插件 chinese ,也可以直接ctrlshiftp快捷鍵也會出來如圖所示圖標&#xff0c;出來chinese 插件之后選擇安裝install,安裝完成之后重新ctrlshiftp會出現如圖所示頁面 找到我的鼠標在的地方對應的中文&#xff0c;此時…

win10下如何安裝ffmpeg

安裝ffmpeg之前先安裝win10 綠色軟件管理軟件&#xff1a;scoop. Scoop的基本介紹 Scoop是一款適用于Windows平臺的命令行軟件&#xff08;包&#xff09;管理工具&#xff0c;這里是Github介紹頁。簡單來說&#xff0c;就是可以通過命令行工具&#xff08;PowerShell、CMD等…

VVIC-商品詳情

一、接口參數說明&#xff1a; item_get-根據ID取商品詳情&#xff0c;點擊更多API調試&#xff0c;請移步注冊API賬號點擊獲取測試key和secret 公共參數 請求地址: https://api-gw.onebound.cn/vvic/item_get 名稱類型必須描述keyString是調用key&#xff08;點擊獲取測試k…

第一百一十三回 dart中的getter/setter方法

文章目錄 概念介紹使用方法示例代碼使用擴展 我們在上一章回中介紹了 flutter_screenutil包相關的內容&#xff0c;本章回中將介紹 dart中的setter/getter方法.閑話休提&#xff0c;讓我們一起Talk Flutter吧。 概念介紹 我們在這里介紹的setter/getter方法屬于編程語言中的…

【MongoDB】索引

目錄 一、概述 二、索引的類型 1、單字段索引 2、復合索引 3、其他索引 三、索引的管理 1、索引的創建 2、索引的查看 3、索引的刪除 四、索引的使用 1、執行計劃 2、涵蓋的查詢 一、概述 索引支持在MongoDB中高效地執行查詢。如果沒有索引&#xff0c;MongoDB必須…

Kubernetes pod調度約束[親和性 污點] 生命階段 排障手段

調度約束 Kubernetes 是通過 List-Watch 的機制進行每個組件的協作&#xff0c;保持數據同步的&#xff0c;每個組件之間的設計實現了解耦。 用戶是通過 kubectl 根據配置文件&#xff0c;向 APIServer 發送命令&#xff0c;在 Node 節點上面建立 Pod 和 Container。 APIServer…

springcloud3 hystrix實現服務降級,熔斷,限流以及案例配置

一 hystrix的作用 1.1 降級&#xff0c;熔斷&#xff0c;限流 1.服務降級&#xff1a; A方案出現問題&#xff0c;切換到兜底方案B&#xff1b; 2.服務熔斷&#xff1a;觸發規則&#xff0c;出現斷電限閘&#xff0c;服務降級 3.服務限流&#xff1a;限制請求數量。 二 案例…

ES6學習-Symbol

Symbol 數據類型Symbol&#xff0c;表示獨一無二的值。 對象的屬性名可有兩種類型&#xff0c;一種是原來的字符串&#xff0c;另一種是新增的 Symbol 類型 可以保證不與其他屬性名產生沖突。 let s1 Symbol() let s2 Symbol() console.log(s1, s2, s1 s2)//Symbol() Sy…

liunx exercise

云計算作業 Linux DAY1 1、創建alan1用戶&#xff0c;并使用root用戶切換用戶至alan1用戶。&#xff08;兩種方式切換【加-與不加-】&#xff0c;并總結其效果&#xff09; [rootlocalhost ~]# useradd alan1 [rootlocalhost ~]# su alan1 [alan1localhost root]$ pwd /roo…

FPGA學習——驅動WS2812光源并進行動態顯示

文章目錄 一、WS2812手冊分析1.1 WS2812燈源特性及概述1.2 手冊重點內容分析1.2.1 產品概述1.2.2 碼型及24bit數據設計 二、系統設計2.1 模塊設計2.2 模塊分析2.2.1 驅動模塊2.2.1 數據控制模塊 三、IP核設置及項目源碼3.1 MIF文件設計3.2 ROM IP核調用3.3 FIFO IP核調用3.4 項…

源碼斷點分析Spring的占位符(Placeholder)是怎么工作的

項目中經常需要使用到占位符來滿足多環境不同配置信息的需求&#xff0c;比如&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <beans xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xmlns"http://www.springframe…

InnoDB文件物理結構解析7 - FIL_PAGE_SDI

在數據庫系統中&#xff0c;通常包含數據字典(data dictionary)用于記錄數據庫對象的元數據(表&#xff0c;分區&#xff0c;觸發器&#xff0c;存儲過程&#xff0c;函數的定義)&#xff0c;我們可以通過information_schema(i_s)數據庫下的視圖(view)或者SHOW語句來訪問數據字…

【愛書不愛輸的程序猿】CPOLAR+HFS,低成本搭建NAS

歡迎來到愛書不愛輸的程序猿的博客, 本博客致力于知識分享&#xff0c;與更多的人進行學習交流 通過HFS低成本搭建NAS&#xff0c;并內網穿透實現公網訪問 - cpolar 極點云 前言1.下載安裝cpolar1.1 設置HFS訪客1.2 虛擬文件系統 2. 使用cpolar建立一條內網穿透數據隧道2.1 保留…