日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Effective Java(一)———— 代替构造器和Setter的构建器模式

發(fā)布時(shí)間:2025/3/12 java 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Effective Java(一)———— 代替构造器和Setter的构建器模式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

引言

Java語(yǔ)言中的一部經(jīng)典著作《Effective Java》,里面涵蓋了78條我們應(yīng)該熟練的Java編程技巧。

本篇博客是該書學(xué)習(xí)的系列筆記第一篇。本系列博客不會(huì)與書中的78條建議完全匹配。只是以一種讀者的身份來(lái)記錄和總結(jié)從書中得到的好的編程建議,博客中會(huì)明確從書中哪條建議得來(lái)的知識(shí)。

本博客總結(jié)自書中第二條:遇到多個(gè)構(gòu)造器參數(shù)時(shí)要考慮用構(gòu)建器

構(gòu)建器的產(chǎn)生

我們知道對(duì)象的構(gòu)建有很多種方式:構(gòu)造器、靜態(tài)工廠、Setter。

通常,最傻瓜式的對(duì)象構(gòu)建方式是:通過(guò)new關(guān)鍵字,調(diào)用一個(gè)默認(rèn)的無(wú)參構(gòu)造,然后向這個(gè)對(duì)象中set各種屬性。

第二種稍微上點(diǎn)檔次的方式是使用構(gòu)造器。為一個(gè)JavaBean創(chuàng)建一個(gè)有參構(gòu)造,在new的時(shí)候通過(guò)有參構(gòu)造來(lái)構(gòu)建這個(gè)bean。

第三種是靜態(tài)工廠,簡(jiǎn)單的說(shuō)也是通過(guò)一個(gè)靜態(tài)方法,來(lái)調(diào)用一個(gè)有參構(gòu)造,來(lái)構(gòu)建對(duì)象。

這三種方法貌似都沒(méi)什么問(wèn)題。但是設(shè)想一下這樣的場(chǎng)景:

一個(gè)JavaBean中有很多屬性,大于5個(gè),這些屬性有些是必需的,有些是可選的,如何來(lái)選擇構(gòu)建對(duì)象的方式?

上述三種方式:有參構(gòu)造、靜態(tài)工廠、Setter屬性,依然可以達(dá)到場(chǎng)景的要求。但是它們?cè)诿鎸?duì)大量可選參數(shù)的情況下并不能很好的擴(kuò)展。原因如下:

有參構(gòu)造(或靜態(tài)工廠):需要提供針對(duì)可選參數(shù)的多個(gè)不同參數(shù)列表的構(gòu)造器,從而滿足不同場(chǎng)景下對(duì)可選參數(shù)的賦值,不同構(gòu)造器之間參數(shù)列表的差別很細(xì)微,可讀性非常差,這種方式叫“重疊構(gòu)造器”。

Setter屬性:這種方式雖然比較靈活,但是有可能有線程安全問(wèn)題,因?yàn)樵谡{(diào)用構(gòu)造器與set方法之間,對(duì)象并未完全構(gòu)建完畢,這個(gè)時(shí)候如果在多線程的環(huán)境下有可能使未完成構(gòu)建的對(duì)象處于一種不安全的狀態(tài)。這種方式叫“JavaBeans模式”。

總之一句話:重疊構(gòu)造器(或重疊靜態(tài)工廠)可以構(gòu)造出線程安全的JavaBean,但是可讀性差,擴(kuò)展性不強(qiáng);而JavaBeans模式,雖然可讀性好,靈活,但是不具備線程安全性,可能發(fā)生線程安全問(wèn)題。

這就產(chǎn)生了新的構(gòu)造對(duì)象的方式:構(gòu)建器。它是“建造者模式”的一種形式,同時(shí)具備靈活性、線程安全性、可讀性等多種優(yōu)點(diǎn),但是可能也要面臨額外的編碼量、理解難度、可能存在的性能開(kāi)銷等問(wèn)題。一般在某個(gè)對(duì)象含有大量可選參數(shù)的情況下使用構(gòu)建器。

構(gòu)建器的使用

說(shuō)了這么多,到底構(gòu)建器是什么?我們?nèi)绾问褂脴?gòu)建器呢?

首先需要明確一點(diǎn),構(gòu)建器是用于構(gòu)建一個(gè)對(duì)象的。它兼顧了構(gòu)造器的優(yōu)點(diǎn)和setter的優(yōu)點(diǎn)。

客戶端使用一個(gè)構(gòu)建器需要完成三件事:

1、不直接生成目標(biāo)對(duì)象,而是讓客戶端代碼利用所有必需參數(shù)調(diào)用構(gòu)造器(或靜態(tài)工廠)創(chuàng)建builder對(duì)象(builder對(duì)象用于后續(xù)目標(biāo)對(duì)象的創(chuàng)建和賦值工作)。

2、客戶端在builder對(duì)象上調(diào)用類似Setter方法,來(lái)設(shè)置每個(gè)可選參數(shù)。

3、客戶端調(diào)用無(wú)參的builder()方法生成目標(biāo)對(duì)象。

?因此,客戶端代碼可以像下面這樣:

// 客戶端代碼使用必需參數(shù)創(chuàng)建一個(gè)builder對(duì)象 Student stu = new Student.StudentBuilder(10001, "張三", 1, 17)// 必須參數(shù):學(xué)號(hào)、姓名、性別、年齡.headTeacherName("張老師") // 可選參數(shù):班主任名稱.className("三年一班") // 可選參數(shù):班級(jí)名稱.address("朝陽(yáng)區(qū)-潘家園") // 可選參數(shù):家庭住址.specialty("硬筆書法") // 可選參數(shù):特長(zhǎng).build();

?可以看到上面的代碼中,一條語(yǔ)句就完成了對(duì)學(xué)生對(duì)象的創(chuàng)建,沒(méi)有使用setter方法將可選參數(shù)的設(shè)置與構(gòu)造器分開(kāi),因此不會(huì)存在線程安全問(wèn)題,可讀性也非常強(qiáng),可選參數(shù)可以根據(jù)不同的場(chǎng)景自由剪裁,因此擴(kuò)展性也非常高。

構(gòu)建器的創(chuàng)建

和構(gòu)造器和Setter方法一樣,我們同樣需要在定義JavaBean對(duì)象的類中定義一個(gè)構(gòu)建器,讓它來(lái)完成對(duì)目標(biāo)對(duì)象的構(gòu)建工作。

同樣,構(gòu)建器的編碼工作我們需要注意幾個(gè)關(guān)鍵步驟:

1、構(gòu)建器實(shí)際上是一個(gè)靜態(tài)成員類

2、構(gòu)建器類中擁有所有目標(biāo)對(duì)象的屬性

3、構(gòu)建器類擁有設(shè)置必需參數(shù)的構(gòu)造器設(shè)置每個(gè)可選參數(shù)的“類似Setter方法”

4、“類Setter方法”返回構(gòu)建器對(duì)象本身

5、構(gòu)建器有一個(gè)無(wú)參的build()方法,用于創(chuàng)建目標(biāo)對(duì)象

6、目標(biāo)類有唯一的私有構(gòu)造器,構(gòu)造器參數(shù)就是構(gòu)建器對(duì)象,這個(gè)構(gòu)造器的工作就是將參數(shù)中的每個(gè)屬性一 一賦值給目標(biāo)對(duì)象。

和前面客戶端創(chuàng)建Student對(duì)象對(duì)應(yīng)的Student類代碼如下:

public class Student {// 必需參數(shù)private int stuNo;private String name;private int gender;// 性別:0代表女生;1代表男生private int age; // // 可選參數(shù)private String headTeacherName;// 班主任名稱private String address;// 家庭住址private String className;//班級(jí)名稱private String specialty;//特長(zhǎng)private Student(StudentBuilder builder) {this.stuNo = builder.stuNo;this.name = builder.name;this.gender = builder.gender;this.age = builder.age;this.headTeacherName = builder.headTeacherName;this.address = builder.address;this.className = builder.className;this.specialty = builder.specialty;}/** 用于構(gòu)建Student對(duì)象的構(gòu)建器類*/public static class StudentBuilder {// 必需private int stuNo;private String name;private int gender;private int age;// 可選private String headTeacherName;// 班主任名稱private String address;// 家庭住址private String className;//班級(jí)名稱private String specialty;//特長(zhǎng)public StudentBuilder(int stuNo, String name, int gender, int age) {this.stuNo = stuNo;this.name = name;this.gender = gender;this.age = age;}public StudentBuilder headTeacherName(String headTeacherName) {this.headTeacherName = headTeacherName;return this;}public StudentBuilder address(String address) {this.address = address;return this;}public StudentBuilder className(String className) {this.className = className;return this;}public StudentBuilder specialty(String specialty) {this.specialty = specialty;return this;}public Student build() {return new Student(this);}} }

建議給Student添加一個(gè)toString()方法,并執(zhí)行一下客戶端代碼:通過(guò)構(gòu)建器創(chuàng)建Student對(duì)象并輸出它。

可以看到,使用構(gòu)建器的方式確實(shí)增加了一部分編碼量,因此,并不是以后所有的情況都是用構(gòu)建器模式才算好的代碼。這種構(gòu)建器模式通常用于參數(shù)較多的情況下。

總結(jié)

構(gòu)建器可以解決因?yàn)榇罅靠蛇x參數(shù)使用重疊構(gòu)造器導(dǎo)致客戶端代碼編碼困難、代碼可讀性差、擴(kuò)展性不強(qiáng)等缺點(diǎn);同時(shí)具備類似Setter的靈活度和可讀性。

同時(shí),剖析了構(gòu)建器實(shí)現(xiàn)的本質(zhì)后,我們是否也可以簡(jiǎn)化這種構(gòu)建器實(shí)現(xiàn)方式呢?當(dāng)然可以,一個(gè)簡(jiǎn)單的JavaBean,讓它的有參構(gòu)造傳入所有必需的參數(shù),而它的Setter方法將void改為返回當(dāng)前JavaBean對(duì)象不就完全可以達(dá)到這種串行構(gòu)建對(duì)象的效果嗎?書中構(gòu)建器后半部分的闡述中提到了強(qiáng)加驗(yàn)證的思想,但并沒(méi)有提供代碼的實(shí)現(xiàn)思路和案例,因此在真正使用構(gòu)建器的時(shí)候我們依然可以繼續(xù)深入的研究構(gòu)建器的使用方式,真正的掌握構(gòu)建器的使用。

以上就是構(gòu)建器的學(xué)習(xí)和使用,歡迎大家文末留言討論。

總結(jié)

以上是生活随笔為你收集整理的Effective Java(一)———— 代替构造器和Setter的构建器模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。