網站首頁 編程語言 正文
前言
Builder模式大家應該不陌生,在我們的編碼生涯中,總會碰到它的身影。無論是Android開發中的AlertDialog,還是網絡框架中的OkHttp和Retrofit,亦或是JavaPoet中,都有這哥們的身影。
之所以它這么受歡迎,除了它的上手難度比較低以外,還有一點就是它的的確確的解決了我們日常開發中的一個難題,創建對象時需要的參數過多。
舉個小例子
過去幾年大家都流行炒幣,導致市面上一卡難求。隨著政府政策的出臺,以及虛擬貨幣的崩盤。顯卡不再是有價無市的一種狀態。大學剛畢業的小龍開了個電腦店,專門給人配電腦。最開始的時候需求比較簡單,只給人記錄電腦的CPU,GPU,硬盤等相關信息。
傳統的創建對象方式
// 電腦類
class Computer {
private String mBroad;
private String mCPU;
private String mGPU;
public Computer(String broad, String CPU, String GPU) {
mBroad = broad;
mCPU = CPU;
mGPU = GPU;
}
@Override
public String toString() {
return "Computer{" +
", mBroad='" + mBroad + ''' +
", mCPU='" + mCPU + ''' +
", mGPU='" + mGPU + ''' +
'}';
}
}
這個時候創建一個Computer對象是這樣的:
Computer computer = new Computer("微星 B550M","INTEL I5","NV 3060TI");
隨著業務量的增大,客戶的要求也越來越多。對鼠標,鍵盤,系統也有了相應的需求。所以Computer類也不得不有了相應的改變。
static class Computer {
private String mOS;
private String mBroad;
private String mKeyBoard;
private String mMouse;
private String mCPU;
private String mGPU;
public Computer(String OS, String broad, String keyBoard, String mouse, String CPU, String GPU) {
mOS = OS;
mBroad = broad;
mKeyBoard = keyBoard;
mMouse = mouse;
mCPU = CPU;
mGPU = GPU;
}
// 就寫一個set方法否則文章太長,其他就不寫了
public void setmBroad(String mBroad) {
this.mBroad = mBroad;
}
@Override
public String toString() {
return "Computer{" +
"mOS='" + mOS + ''' +
", mBroad='" + mBroad + ''' +
", mKeyBoard='" + mKeyBoard + ''' +
", mMouse='" + mMouse + ''' +
", mCPU='" + mCPU + ''' +
", mGPU='" + mGPU + ''' +
'}';
}
}
而創建Computer對象的參數也越來越長:
Computer computer = new Computer("MAC OS","微星 B550M","IQUNIX F97"
,"羅技 MX MASTER3","INTEL I5","NV 3060TI");
如果再有新的需求參數,電源,機箱,散熱,內存條,硬盤......簡直不敢想象。
對象初始化參數問題
此時我們面對的是編程中常見的一個問題,對象中需求的參數過多,而都在構造函數中傳遞,則構造函數就會同例子中一樣,太長,要是用set方法來傳遞,則更為恐怖。
這個時候一個模式就應運而生,他就是建造者模式。
建造者模式處理方式
/**
* @author:TianLong
* @date:2022/10/17 19:58
* @detail:產品類
*/
class Computer{
private String mOS;
private String mBroad;
private String mKeyBoard;
private String mMouse;
private String mCPU;
private String mGPU;
private Computer(String OS, String broad, String keyBoard, String mouse, String CPU, String GPU) {
mOS = OS;
mBroad = broad;
mKeyBoard = keyBoard;
mMouse = mouse;
mCPU = CPU;
mGPU = GPU;
}
public static ComputerBuilder createBuilder(){
return new ComputerBuilder();
}
@Override
public String toString() {
return "Computer{" +
"mOS='" + mOS + ''' +
", mBroad='" + mBroad + ''' +
", mKeyBoard='" + mKeyBoard + ''' +
", mMouse='" + mMouse + ''' +
", mCPU='" + mCPU + ''' +
", mGPU='" + mGPU + ''' +
'}';
}
/**
* @author:TianLong
* @date:2022/10/17 19:58
* @detail:產品建造者類
*/
public static class ComputerBuilder{
private String mOS = "Windows";
private String mBroad= "微星 B550M";
private String mKeyBoard= "無";
private String mMouse= "無";
private String mCPU= "Intel I5";
private String mGPU= "AMD 6600XT";
public ComputerBuilder setOS(String OS) {
mOS = OS;
return this;
}
public ComputerBuilder setBroad(String broad) {
mBroad = broad;
return this;
}
public ComputerBuilder setKeyBoard(String keyBoard) {
mKeyBoard = keyBoard;
return this;
}
public ComputerBuilder setMouse(String mouse) {
mMouse = mouse;
return this;
}
public ComputerBuilder setCPU(String CPU) {
mCPU = CPU;
return this;
}
public ComputerBuilder setGPU(String GPU) {
mGPU = GPU;
return this;
}
public Computer build(){
// 可以在build方法中做一些校驗等其他工作
if (mBroad.contains("技嘉")){
throw new RuntimeException("技嘉辱華,不支持技嘉主板");
}
Computer computer = new Computer(mOS,mBroad,mKeyBoard,mMouse,mCPU,mGPU);
return computer;
}
}
老版本和Builder版本創建對象
// 老版本的Computer對象創建
Computer computer = new Computer("MAC OS","微星 B550M","IQUNIX F97"
,"羅技 MX MASTER3","INTEL I5","NV 3060TI");
// Builder版本的Computer對象創建
Computer computer =Computer.createBuilder()
.setCPU("AMD 5600X")
.setGPU("NV 3060TI")
.setMouse("羅技 MX MASTER3")
.setKeyBoard("IQUNIX F97")
.build();
兩個版本一對比就能體現出來優勢。老版本構造函數中的參數太多太長,同一個類型的參數很容易傳錯位,經常傳參數的時候,還要看看第幾個參數應該傳什么。
Builder模式的對象創建,簡單明了,更容易理解,而且流式的調用更加美觀,不會出錯。
從代碼中可以看到,Computer類的構造函數是私有的,保證了所有對象的創建都必須從ComputerBuilder這個類來創建。且ComputerBuilder這個類的build方法中,可以進行校驗或者其他操作。
同時,Computer這個類中是否存在Set方法,由你的實際應用場景決定,反正我的使用場景里,沒有修改需求。
注意事項
- 上述代碼為常見寫法,并非固定模板。只要能通過Builder類創建目標對象,都可以算是建造者模式。
- 建造者模式中的目標對象的構造函數必須是private修飾。否則可以直接創建對象。Builder類就沒有意義了
- 建造者模式中的目標對象是否需要Set方法,由具體需求決定。一般情況下沒有Set方法,可以避免對該對象中的參數進行修改。
- Builder中的build方法,可以處理一些邏輯問題,比如校驗信息等
- 工廠模式注重的是同一類型的對象中通過參數來控制具體創建哪個對象。Builder模式關注的是單一對象中的參數傳遞。
原文鏈接:https://juejin.cn/post/7197326179934191676
相關推薦
- 2022-12-23 Kubernetes調度管理優先級和搶占機制詳解_云其它
- 2022-04-19 前端開發中幾種存儲方式詳解
- 2023-08-01 前端眼里的多線程,專用Worker線程
- 2022-09-06 Redis與本地緩存的結合實現_Redis
- 2023-04-02 Flutter應用Windows平臺接入實踐詳解_C 語言
- 2022-10-07 C++函數指針與指針函數有哪些關系和區別_C 語言
- 2021-12-11 關于docker容器部署redis步驟介紹_docker
- 2022-10-25 React?中?setState?的異步操作案例詳解_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支