java中的builder模式

我們構(gòu)造一個(gè)類常用的有兩種方式
一種方式是采用多重載的構(gòu)造函數(shù),把不同搭配的屬性寫成不同的構(gòu)造函數(shù)爽待,這種方式的缺點(diǎn)在于代碼的重復(fù)工作量會非常大,而且用戶在用的時(shí)候很難分清楚每一種構(gòu)造函數(shù)是干什么的翩腐,而且參數(shù)順序輸不對可是個(gè)大問題鸟款,使用起來十分不方便。
另一種方法是通過get茂卦,set的方法何什,這種方法比較容易理解,但是缺點(diǎn)也很明顯等龙,一個(gè)是參數(shù)變量不能是final類型处渣,而且用戶不知道什么時(shí)候他才能得到一個(gè)完整的變量(比方說用戶還有很重要的屬性沒有set就去使用這個(gè)變量了)
針對以上的缺點(diǎn),我們采用builder模式去構(gòu)建一個(gè)新的對象

傳統(tǒng)builder模式

圖片來自于朱小廝的博客蛛砰,感謝

傳統(tǒng)建造者模式包含四個(gè)角色

  • builder(抽象構(gòu)造者):這個(gè)是一個(gè)抽象類或者接口罐栈,用于抽象具體建造者的函數(shù)。
  • ConcreteBuilder(具體建造者):這是抽象構(gòu)造者的具體實(shí)現(xiàn)泥畅,實(shí)現(xiàn)構(gòu)造邏輯
  • Director (指導(dǎo)者):可以叫指導(dǎo)者荠诬,也可以叫服務(wù)員,他不需要知道builder是如何建造產(chǎn)品的,用戶直接和指導(dǎo)者進(jìn)行溝通柑贞,指導(dǎo)者有兩種操作:告訴builder去建造一個(gè)商品方椎;把商品交付給用戶
  • Product (產(chǎn)品類):這是我們具體要構(gòu)造的的對象。

代碼

產(chǎn)品類

public class Car
{
    private String wheel;
    private String skeleton;
    private String engine;
// 省略getter和setter方法
}

抽象建造者類

public interface ICarBuilder
{
    public void buildWheel();
    public void buildSkeleton();
    public void buildEngine();

    Car buildCar();
}

具體建造者類

public class ConcreteBuilder implements ICarBuilder
{
    Car car;

    public ConcreteBuilder()
    {
        car = new Car();
    }

    @Override
    public ConcreteBuilder buildWheel()
    {
        car.setWheel("輪子");
    }

    @Override
    public ConcreteBuilder buildSkeleton()
    {
        car.setSkeleton("車身結(jié)構(gòu)");
    }

    @Override
    public ConcreteBuilder buildEngine()
    {
        car.setEngine("發(fā)動機(jī)");
    }
//前面那些builder方法返回的都是builder钧嘶,只有當(dāng)調(diào)用下面的build方法的時(shí)候才最終構(gòu)建出了該對象
    @Override
    public Car buildCar()
    {
        return this.car;
    }
}
public class CarDirector
{
    public Car constructCar(ICarBuilder builder)
    {
        builder.buildEngine();
        builder.buildSkeleton();
        builder.buildWheel();
        return builder.buildCar();
    }
}
public class MainTest
{
    public static void main(String[] args)
    {
        CarDirector director = new CarDirector();//在使用的時(shí)候先聲明中間的服務(wù)員棠众,也就是指導(dǎo)者
        Car car = director.constructCar(new ConcreteBuilder());//通過指導(dǎo)者把車構(gòu)建出來
        System.out.println(car.getWheel());
        System.out.println(car.getEngine());
        System.out.println(car.getSkeleton());
    }
}

此段代碼作者朱小廝 原文:https://blog.csdn.net/u013256816/article/details/50978024?utm_source=copy
主要優(yōu)點(diǎn)是

  • 在建造過程中對象是未生成的,最后調(diào)用build方法之后才會生成該對象
  • 有一個(gè)builder的interface有决,擴(kuò)展性更強(qiáng)闸拿,并且可以把build過程與交付給用戶的過程解耦開,使用更靈活疮薇,封裝性好
  • 而且這也形成了漂亮的鏈?zhǔn)秸{(diào)用
Person person = new Person.PersonBuilder("cj")
                .age(24)
                .job("java")
                .location("蘇州")
                .builder();

變種builder模式

在上面的builder模式中胸墙,優(yōu)點(diǎn)顯而易見,可擴(kuò)展性強(qiáng)按咒,但是造成的結(jié)果是代碼冗余量大迟隅,憑空多了三個(gè)類,而且并不是所有的情況都需要多個(gè)不同實(shí)現(xiàn)的builder的励七,變種builder模式的主要目的是減少多余類的創(chuàng)建智袭,省略了builder抽象類和指導(dǎo)者。

代碼

這里主要結(jié)合OKHttp源碼講解

public final class Request {
  final HttpUrl url;
  final String method;
  final Headers headers;
  final RequestBody body;
  final Object tag;

  private volatile CacheControl cacheControl; // Lazily initialized.

  Request(Builder builder) {
    //構(gòu)造函數(shù)掠抬,省略屬性賦值操作
  }

  public Builder newBuilder() {//這里讀者可以思考一下為什么會有一個(gè)newbuilder模式呢
    return new Builder(this);
  }
//省略部分代碼
  public static class Builder {
    HttpUrl url;
    String method;
    Headers.Builder headers;
    RequestBody body;
    Object tag;
//省略部分代碼
    Builder(Request request) {//這里讀者可以想一想為什么在builder中會有這樣一個(gè)構(gòu)造方法吼野,既然我們在創(chuàng)造builder的時(shí)候request是空的,那我們什么時(shí)候會用到這個(gè)方法呢两波?
      //構(gòu)造函數(shù)瞳步,省略屬性賦值操作
    }
//省略部分代碼
     public Request build() {
      if (url == null) throw new IllegalStateException("url == null");
         return new Request(this);
    }
}

在變種builder模式中,直接將指揮者和抽象builder類去掉了腰奋,取而代之的是靜態(tài)內(nèi)部類builder单起,犧牲了一部分的可擴(kuò)展性,將代碼邏輯大大簡化劣坊。

感謝原作者

這種builder的作用和傳統(tǒng)builder是一樣的
這個(gè)時(shí)候有一個(gè)問題嘀倒,當(dāng)我的對象屬性相當(dāng)多,而且我現(xiàn)在要新建一個(gè)對象局冰,這個(gè)對象的屬性值只有一兩個(gè)和我已有的對象不同测蘑,這個(gè)時(shí)候我要怎么做?
粘貼上一段代碼康二?重新輸入?
畢竟builder模式創(chuàng)建的對象一但創(chuàng)建成功里面的屬性就不能再修改碳胳,所以拷貝一個(gè)對象再更改屬性的方法是不可行的
我在一開始讀OKhttp的源碼的時(shí)候也很好奇它里面為什么會有一個(gè)newBuilder方法,builder中會有一個(gè)參數(shù)為request的構(gòu)造方法赠摇,這里不得不驚嘆設(shè)計(jì)者的強(qiáng)大固逗,原文在此

public Builder newBuilder() {
    return new Builder(this);
  }

這里通過原有的request的newBuilder方法生成一個(gè)新的浅蚪,并且屬性值和request一樣的builder,之后再用這個(gè)新的builder更改屬性后生成新的request烫罩。


3a1e797ababcd9d1a2c7f031a6670ad7.png

巧妙地通過產(chǎn)品構(gòu)造出builder惜傲,更改builder產(chǎn)生全新的產(chǎn)品。通過逆向構(gòu)造的過程完成了整個(gè)拷貝

對比傳統(tǒng)builder模式和變種builder模式

傳統(tǒng)的builder模式優(yōu)點(diǎn)是可擴(kuò)展性強(qiáng)贝攒,但是同時(shí)缺點(diǎn)是要?jiǎng)?chuàng)造4個(gè)類盗誊,對于初學(xué)者很不友好,而且代碼冗余量大隘弊,變種builder使用更加便捷哈踱,操作更加方便

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市梨熙,隨后出現(xiàn)的幾起案子开镣,更是在濱河造成了極大的恐慌,老刑警劉巖咽扇,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件邪财,死亡現(xiàn)場離奇詭異,居然都是意外死亡质欲,警方通過查閱死者的電腦和手機(jī)树埠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嘶伟,“玉大人怎憋,你說我怎么就攤上這事【琶粒” “怎么了绊袋?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铸鹰。 經(jīng)常有香客問我愤炸,道長,這世上最難降的妖魔是什么掉奄? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮凤薛,結(jié)果婚禮上姓建,老公的妹妹穿的比我還像新娘。我一直安慰自己缤苫,他們只是感情好速兔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著活玲,像睡著了一般涣狗。 火紅的嫁衣襯著肌膚如雪谍婉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天镀钓,我揣著相機(jī)與錄音穗熬,去河邊找鬼。 笑死丁溅,一個(gè)胖子當(dāng)著我的面吹牛唤蔗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窟赏,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼妓柜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了涯穷?” 一聲冷哼從身側(cè)響起棍掐,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拷况,沒想到半個(gè)月后作煌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蝠嘉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年最疆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚤告。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡努酸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出杜恰,到底是詐尸還是另有隱情获诈,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布心褐,位于F島的核電站舔涎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏逗爹。R本人自食惡果不足惜亡嫌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掘而。 院中可真熱鬧挟冠,春花似錦、人聲如沸袍睡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽斑胜。三九已至控淡,卻和暖如春嫌吠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背掺炭。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工辫诅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人竹伸。 一個(gè)月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓泥栖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親勋篓。 傳聞我的和親對象是個(gè)殘疾皇子吧享,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法譬嚣,內(nèi)部類的語法钢颂,繼承相關(guān)的語法,異常的語法拜银,線程的語...
    子非魚_t_閱讀 31,623評論 18 399
  • 對象的創(chuàng)建與銷毀 Item 1: 使用static工廠方法殊鞭,而不是構(gòu)造函數(shù)創(chuàng)建對象:僅僅是創(chuàng)建對象的方法,并非Fa...
    孫小磊閱讀 1,981評論 0 3
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,958評論 6 13
  • 在大河轉(zhuǎn)折處尼桶,我們曾經(jīng)經(jīng)歷風(fēng)雨操灿,遇見彩虹。那些寶貴的經(jīng)歷泵督,都變成了珍貴的回憶趾盐。 時(shí)間過得那么快啊...
    惠天使閱讀 433評論 2 5
  • YARN環(huán)境的搭建 搭建的簡介: 搭建YARN的過程也非常的簡單,因?yàn)槲乙呀?jīng)搭建過HDFS系統(tǒng)了整個(gè)流程只需要改配...
    陳_志鵬閱讀 2,588評論 0 2