設計模式 建造者模式 與 Spring Bean建造者 BeanDefinitionBuilder 源碼與應用

建造者模式

  1. 定義: 將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示
  2. 主要作用: 在用戶不知道對象的建造過程和細節的情況下就可以直接創建復雜的對象
  3. 如何使用: 用戶只需要給出指定復雜對象的類型和內容, 建造者模式負責按順序創建復雜對象(把內部的建造過程和細節隱藏起來)
  4. 解決的問題:
  • 方便用戶創建復雜的對象 不需要知道實現過程
  • 代碼復用性/封裝性 將對象構建過程和細節進行封裝/復用
  1. 注意事項: 與工廠模式的區別 建造者模式更加關注與零件裝配的順序, 一般用來創建更為復雜的對象

建造者一般有如下四個角色

  1. 產品(Product): 要創建的產品類對象
  2. 抽象建造者(Builder): 建造者的抽象類, 一般用來定義建造細節的方法, 并不涉及具體的對象部件的創建
  3. 具體建造者(ConcreteBuilder): 具體的Builder類, 根據不同的業務邏輯, 實現對象的各個組成部分的創建
  4. 調度者(Director): 調用具體建造者來創建復雜產品(Product)的各個部分, 并按照一定順序或流程, 來建造復雜對象

簡單實現建造者模式

產品(Product)

/*** @author LionLi*/
public class Product {private Long id;private String name;private String number;private Integer type;private String description;// ----- get set -----
}

建造者(ProductBuilder)將復雜的構建過程封裝起來, 這里如果有多種產品的建造者可以抽象出一個抽象建造者將實現交給不同產品的具體建造者子類

/*** @author LionLi*/
public class ProductBuilder {private final Product product = new Product();public void id(Long id) {product.setId(id);}public void name(String name) {product.setName(name);}public void number(String number) {product.setNumber(number);}public void type(Integer type) {product.setType(type);}public void description(String description) {product.setDescription(description);}public Product build() {return product;}
}

測試類

/*** @author LionLi*/
public class Test {public static void main(String[] args) {ProductBuilder builder = new ProductBuilder();builder.id(1L);builder.name("666");builder.number("CP123");builder.type(1);builder.description("測試");System.out.println(builder.build());}
}

鏈式建造者寫法

在平常的應用中, 建造者模式通常是采用鏈式編程的方式構建對象, 修改ProductBuilder代碼

/*** 鏈式建造者** @author LionLi*/
public class ProductBuilder {private final Product product = new Product();public ProductBuilder id(Long id) {product.setId(id);return this;}public ProductBuilder name(String name) {product.setName(name);return this;}public ProductBuilder number(String number) {product.setNumber(number);return this;}public ProductBuilder type(Integer type) {product.setType(type);return this;}public ProductBuilder description(String description) {product.setDescription(description);return this;}public Product build() {return product;}
}

測試類

/*** @author LionLi*/
public class Test {public static void main(String[] args) {ProductBuilder builder = new ProductBuilder();Product product = builder.id(1L).name("666").number("CP123").type(1).description("測試鏈式").build();System.out.println(product);}
}

Lombok @Builder 注解實現建造者模式

我們項目中最常使用的 Lombok 工具是如何實現的建造者呢, 我們來看一下

改造產品類適用 @Builder 注解, 只需要增加一個注解即可完成建造者模式是不是非常的簡單

/*** @author LionLi*/
@Data
@Builder
public class Product {private Long id;private String name;private String number;private Integer type;private String description;
}

測試類

/*** @author LionLi*/
public class Test {public static void main(String[] args) {Product.ProductBuilder builder = Product.builder();Product product = builder.id(1L).name("666").number("CP123").type(1).description("測試鏈式").build();System.out.println(product);}
}

我們來看一下 Lombok 是如何實現的建造者模式

進入代碼目錄下的target目錄找到class下的編譯后的Product

首先是Product本身

然后是建造者ProductBuilder


可以看出跟我們上面寫的幾乎是相同的

Spring中建造者模式的應用

Spring框架中的建造者模式的應用有很多, 例如BeanDefinitionBuilder用于構建Bean定義信息對象, 將BeanDefinition的創建過程進行封裝, 并提供BeanDefinitionBuilder各種Bean定義信息對象的創建方法, 其實現更加的簡潔并且符合實際開發需求.

大家可以搜索找到 BeanDefinitionBuilder 類查看實現

BeanDefinitionBuilder 代碼, 可以看出bean的構建過程還是很復雜的每個方法都做了很多操作

/*** Programmatic means of constructing* {@link org.springframework.beans.factory.config.BeanDefinition BeanDefinitions}* using the builder pattern. Intended primarily for use when implementing Spring 2.0* {@link org.springframework.beans.factory.xml.NamespaceHandler NamespaceHandlers}.** @author Rod Johnson* @author Rob Harrop* @author Juergen Hoeller* @since 2.0*/
public final class BeanDefinitionBuilder {/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link GenericBeanDefinition}.*/public static BeanDefinitionBuilder genericBeanDefinition() {return new BeanDefinitionBuilder(new GenericBeanDefinition());}/*** Create a new {@code BeanDefinitionBuilder} used to construct a {@link GenericBeanDefinition}.* @param beanClassName the class name for the bean that the definition is being created for*/public static BeanDefinitionBuilder genericBeanDefinition(String beanClassName) {BeanDefinitionBuilder builder = new BeanDefinitionBuilder(new GenericBeanDefinition());builder.beanDefinition.setBeanClassName(beanClassName);return builder;}// ----- 太多了省略部分代碼 -----/*** The {@code BeanDefinition} instance we are creating.*/private final AbstractBeanDefinition beanDefinition;/*** Our current position with respect to constructor args.*/private int constructorArgIndex;/*** Enforce the use of factory methods.*/private BeanDefinitionBuilder(AbstractBeanDefinition beanDefinition) {this.beanDefinition = beanDefinition;}/*** Return the current BeanDefinition object in its raw (unvalidated) form.* @see #getBeanDefinition()*/public AbstractBeanDefinition getRawBeanDefinition() {return this.beanDefinition;}/*** Validate and return the created BeanDefinition object.*/public AbstractBeanDefinition getBeanDefinition() {this.beanDefinition.validate();return this.beanDefinition;}/*** Set the name of a static factory method to use for this definition,* to be called on this bean's class.*/public BeanDefinitionBuilder setFactoryMethod(String factoryMethod) {this.beanDefinition.setFactoryMethodName(factoryMethod);return this;}/*** Add an indexed constructor arg value. The current index is tracked internally* and all additions are at the present point.*/public BeanDefinitionBuilder addConstructorArgValue(@Nullable Object value) {this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(this.constructorArgIndex++, value);return this;}/*** Add a reference to a named bean as a constructor arg.* @see #addConstructorArgValue(Object)*/public BeanDefinitionBuilder addConstructorArgReference(String beanName) {this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(this.constructorArgIndex++, new RuntimeBeanReference(beanName));return this;}// ----- 太多了省略部分代碼 -----/*** Append the specified bean name to the list of beans that this definition* depends on.*/public BeanDefinitionBuilder addDependsOn(String beanName) {if (this.beanDefinition.getDependsOn() == null) {this.beanDefinition.setDependsOn(beanName);}else {String[] added = ObjectUtils.addObjectToArray(this.beanDefinition.getDependsOn(), beanName);this.beanDefinition.setDependsOn(added);}return this;}/*** Set whether this bean is a primary autowire candidate.* @since 5.1.11*/public BeanDefinitionBuilder setPrimary(boolean primary) {this.beanDefinition.setPrimary(primary);return this;}/*** Apply the given customizers to the underlying bean definition.* @since 5.0*/public BeanDefinitionBuilder applyCustomizers(BeanDefinitionCustomizer... customizers) {for (BeanDefinitionCustomizer customizer : customizers) {customizer.customize(this.beanDefinition);}return this;}}

BeanDefinitionBuilder的應用

大家可以搜索找到 AbstractSingleBeanDefinitionParser 類查看實現

AbstractSingleBeanDefinitionParser 是一個解析并生成單例Bean對象的解析器, BeanDefinitionBuilder具體如何創建Bean實例的可以查看這個類的實現

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

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

相關文章

java 布隆過濾器_什么是布隆過濾器(Bloom Filter)?

在日常工作中,有一個比較常見的需求,就是需要判斷一個元素是否在集合中。例如以下場景:給定一個IP黑名單庫,檢查指定IP是否在黑名單中?在接收郵件的時候,判斷一個郵箱地址是否為垃圾郵件?在文字…

STM32上使用JSON

一、STM32工程中添加JSON 最近在一網2串項目,串口和網口之間可能需要定義一下簡單的通信協議,而通信協議上則需要去定義一下通信的數據格式,上次聽劍鋒說要用Json來定義,目前查了下資料具體如何去應用還不 會。因為最新的KEIL上支…

Flex 學習

Flex案例一&#xff1a; 1 <html>2 <head>3 <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> 4 <title>無標題</title>5 <style type"text/css">6 body,h1,h2,h3,h4,…

Cocos2d-X中實現自己定義菜單處理事件

當用戶點擊再松開后才會響應菜單事件&#xff0c;而在游戲中有些游戲須要玩家點擊后就處理事件。如玩坦克大戰的時候&#xff0c;玩家是點擊一下就發射子彈。并是點擊松手后發射子彈&#xff0c;在Cocos2d-X中沒有這樣的消息。以下就通過自己定義的方式實現當用戶點擊后就調用處…

java linkedhashset_java之LinkedHashSet

LinkedHashSet是Set集合的一個實現&#xff0c;具有set集合不重復的特點&#xff0c;同時具有可預測的迭代順序&#xff0c;也就是我們插入的順序。并且linkedHashSet是一個非線程安全的集合。如果有多個線程同時訪問當前linkedhashset集合容器&#xff0c;并且有一個線程對當前…

使用Spring Integration輪詢http端點

如果您想用Spring Integration編寫一個流程來輪詢HTTP端點并從http端點收集一些內容以進行進一步處理&#xff0c;那有點不直觀。 Spring Integration提供了幾種與HTTP端點集成的方式- Http出站適配器–將消息發送到http端點 Http出站網關–將消息發送到http端點并收集響應作…

python模塊離線安裝_離線安裝db2的python模塊ibm_db

1、為什么要離線安裝 沒網&#xff0c;在銀行工作&#xff0c;服務器環境配置&#xff0c;完全離線&#xff08;本來五分鐘搞定的事情&#xff0c;非要搞一天。我服&#xff01;&#xff01;&#xff09; 2、安裝步驟 視情況而定。 3。一個下載db2的client包&#xff0c;官網下…

Jmeter 場景設計

今天的業務場景是&#xff1a; 1.管理員登錄后臺---登錄成功后添加一個某類型的產品---產品添加成功后&#xff0c;再為該產品添加10個排期。 2.管理員登錄后臺--登錄成功后添加多個不同類型產品---產品全部添加完成后&#xff0c;依次為所有產品添加10個排期。 這是兩種不同的…

Android IPC機制(五)用Socket實現跨進程聊天程序

1.Socket簡介 Socket也稱作“套接字“&#xff0c;是在應用層和傳輸層之間的一個抽象層&#xff0c;它把TCP/IP層復雜的操作抽象為幾個簡單的接口供應用層調用以實現進程在網絡中通信。它分為流式套接字和數據包套接字&#xff0c;分別對應網絡傳輸控制層的TCP和UDP協議。TCP協…

ArcGIS 網絡分析[4] 網絡數據集深入淺出之連通性、網絡數據集的屬性及轉彎要素...

前面介紹完了如何創建網絡數據集、如何使用網絡分析功能&#xff0c;當然還有的讀者會迷惑于一些更深層次的問題&#xff0c;比如網絡數據集的連通性問題等。 因為不可能面面俱到&#xff0c;我只能挑重點來闡述&#xff0c;我覺得網絡數據集的連通性、屬性和轉彎是初學者中比較…

java獲取byte 長度_java獲取字節的長度.

我們經常要獲取中文,數字,或者英文字符所占字節的長度,下面就列出各種編碼格式下所占字節的長度:代碼如下:package pack.java.midea.dao;import java.io.UnsupportedEncodingException;/*** 測試;* author zhouhaitao* 2012-5-17*/public class Test {/*** param args* throws …

Batoo JPA –比領先的JPA提供商快15倍

介紹 我早在2000年代就喜歡JPA 1.0。 我甚至在穩定版本發布之前就將其與EJB 3.0一起使用。 我非常喜歡它&#xff0c;因此我為JBoss 3.x實現貢獻了一些零碎的部分。 那時我們公司規模還很小。 創建新功能和應用程序比性能更重要&#xff0c;因為我們有很多想法&#xff0c;我…

python軟件是哪個國家的品牌_有哪些好用的軟件被國人誤認為是外國研發的?

國產軟件被標榜上了英文&#xff0c;即便不是英文&#xff0c;用拼音寫出來&#xff0c;也會有人誤認為是國外的軟件。因為這樣可以顯得高大上&#xff0c;為什么我們會有這樣的想法&#xff0c;是崇洋媚外嗎&#xff0c;并不是&#xff0c;而是之前的國產軟件的確有不少讓我們…

簡單的Session案例 —— 一次性驗證碼

一次性驗證碼的主要目的就是為了限制人們利用工具軟件來暴力猜測密碼&#xff0c;其原理與利用Session防止表單重復提交的原理基本一樣&#xff0c;只是將表單標識號變成了驗證碼的形式&#xff0c;并且要求用戶將提示的驗證碼手工填寫進一個表單字段中&#xff0c;而不是通過表…

[BZOJ2064]分裂

[BZOJ2064]分裂 試題描述 背景&#xff1a; 和久必分&#xff0c;分久必和。。。 題目描述&#xff1a; 中國歷史上上分分和和次數非常多。。通讀中國歷史的WJMZBMR表示毫無壓力。 同時經常搞OI的他把這個變成了一個數學模型。 假設中國的國土總和是不變的。 每個國家都可以用他…

CSS3選擇器

基本選擇器 回顧選擇器 通配符選擇器元素選擇器類選擇器ID選擇器后代選擇器新增基本選擇器 子元素選擇器相鄰兄弟選擇器通用兄弟選擇器群組選擇器 子元素選擇器 概念&#xff1a;子元素選擇器只能選擇某元素的子元素 語法&#xff1a;父元素 > 子元素 &#xff08;Fathe…

eclipse java工程目錄_轉載:Eclipse下的java工程目錄

對新手來講&#xff0c;一個Java工程內部的多個文件夾經常會讓大家困惑。更可惡的是莫名其妙的路徑問題&#xff0c;在Eclipse編寫Java程序中&#xff0c;出現頻率最高的錯誤很可能就是路徑問題。這些問題原因其實都是一個&#xff0c;就是關于Java工程內的文件結構理解不清&am…

作為JBoss AS 7模塊運行Drools 5.4.0 Final

Drools 5引入了業務邏輯集成平臺&#xff0c;該平臺為規則&#xff0c;工作流和事件處理提供了統一的集成平臺。 它是從頭開始設計的&#xff0c;因此每個方面都是一流的公民&#xff0c;毫不妥協。 Drools 5已分為4個主要子項目&#xff1a; Drools Guvnor&#xff08;BRMS …

postgres 支持的線程數_線程池被打滿了怎么處理呢,你是否真的了解線程池?

0、前言線程池&#xff0c;顧名思義就是線程的池子&#xff0c;在每次需要取線程去執行任務的時候&#xff0c;沒必要每次都創建新線程執行&#xff0c;線程池就是起著維護線程的作用&#xff0c;當有任務的時候就取出一個線程執行&#xff0c;如果任務執行完成則把線程放回到池…

[樹形DP]沒有上司的舞會

題目鏈接 思考 首先本題中的關系是一種樹形結構&#xff0c;而且符號最優子結構和無后效性&#xff0c;所以可以進行記憶化搜索。 那么首先要在這顆樹中選出一個點作為根節點&#xff0c;按照習慣我們將沒有父節點的點作為根節點。 接下來要思考的是 狀態&#xff1a; dp[i][0…