Android常見(jiàn)設(shè)計(jì)模式十:Build模式

對(duì)于開發(fā)人員來(lái)說(shuō),設(shè)計(jì)模式有時(shí)候就是一道坎,但是設(shè)計(jì)模式又非常有用,過(guò)了這道坎,它可以讓你水平提高一個(gè)檔次。而在android開發(fā)中,必要的了解一些設(shè)計(jì)模式又是必須的,因?yàn)樵O(shè)計(jì)模式在Android源碼中,可以說(shuō)是無(wú)處不在。對(duì)于想系統(tǒng)的學(xué)習(xí)設(shè)計(jì)模式的同學(xué),這里推薦一本書,《大話設(shè)計(jì)模式》。


Android常用設(shè)計(jì)模式系列:

面向?qū)ο蟮幕A(chǔ)特征
面向?qū)ο蟮脑O(shè)計(jì)原則
單例模式
模板模式
適配器模式
工廠模式
代理模式
原型模式
策略模式
Build模式
觀察者模式
裝飾者模式
中介模式
門面模式


Build模式

Build模式是非常常見(jiàn)的設(shè)計(jì)模式之一,寫個(gè)筆記,記錄一下我的學(xué)習(xí)過(guò)程和心得。

首先了解一些Build模式的定義。

將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表示

但是看完這個(gè)定義,并沒(méi)有什么卵用,你依然不知道什么是Builder設(shè)計(jì)模式。在此個(gè)人的態(tài)度是學(xué)習(xí)設(shè)計(jì)模式這種東西,不要過(guò)度在意其定義,定義往往是比較抽象的,學(xué)習(xí)它最好的例子就是通過(guò)樣例代碼。

我們通過(guò)一個(gè)例子來(lái)引出Builder模式。假設(shè)有一個(gè)Car類,我們通過(guò)該Car類來(lái)構(gòu)建一大批汽車,這個(gè)Car類里有很多屬性,最常見(jiàn)的比如顏色,價(jià)格,品牌,排量等等,并且我們?cè)试S這些值不被設(shè)置,也就是允許為null,該類的定義如下。

public class Car  {
    Color color;
    double price;
    String brand;
    String displacement;

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getDisplacement() {
        return displacement;
    }

    public void setDisplacement(String displacement) {
        this.displacement = displacement;
    }
}

然后我們?yōu)榱朔奖憧赡軙?huì)定義一個(gè)構(gòu)造方法。

public Car(Color color, double price, String brand, String displacement) {
 this.color = color;
 this.price = price;
 this.brand = brand;
 this. displacement = displacement;
}

有時(shí)候,只想傳部分參數(shù),你還會(huì)定義如下類似的構(gòu)造方法。

public Car(Color color) {
 this.color = color;
}
 public Car(Color color, double price) {
 this.color = color;
 this.price = price;
}
 public Car(Color color, double price, String brand) {
this.color = color;
 this.price = price;
 this.brand = brand;
} 

于是你就可以這樣創(chuàng)建各個(gè)需要的對(duì)象

Person p2=new Person(Color.read);
Person p3=new Person(Color.blue,180000);
Person p4=new Person(Color.green,21180, "小鵬");
Person p5=new Person(Color.white,17170,"法拉利","4.0L"); 

可以想象一下這樣創(chuàng)建的壞處,如果四個(gè)參都是同一種數(shù)據(jù)類型,那各個(gè)參數(shù)到底是什么意思,那得考讀性了,。還有一個(gè)問(wèn)題就是當(dāng)有很多參數(shù)時(shí),編寫這個(gè)構(gòu)造數(shù)就會(huì)顯得異常麻煩,這時(shí)候如果換一個(gè)角度,試試Builder模式,你會(huì)發(fā)現(xiàn)代碼的可讀性一下子就上去了。

我們給Car增加一個(gè)靜態(tài)內(nèi)部類Builder類,并修改Car類的構(gòu)造函數(shù),代碼如下。

public class Car  {
    Color color;
    double price;
    String brand;
    String displacement;

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        this.color = color;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getDisplacement() {
        return displacement;
    }

    public void setDisplacement(String displacement) {
        this.displacement = displacement;
    }

    private Car(Builder builder) {
 this.color = builder.color;
 this.price = builder.price;
 this.brand = builder.brand;
 this. displacement = builder.displacement;
    }
    
    
    public static class Builder {

    Color color;
    double price;
    String brand;
    String displacement;
        
        public  Builder color(Color color){
            this.color=color;
            return  this;
        }
        public  Builder price(double price){
            this.price=price;
            return  this;
        }
        public  Builder brand(String brand){
            this.brand=brand;
            return  this;
        }
        public  Builder displacement(String displacement){
            this.displacement=displacement;
            return  this;
        }


        public Car build() {
            return new Car(this);
        }
    }
}

這樣,我們就不會(huì)被Car類構(gòu)造函數(shù)的各個(gè)入?yún)⒏愕孟±锖苛恕?br> 此外Builder類中的成員函數(shù)返回Builder對(duì)象自身,讓它支持鏈?zhǔn)秸{(diào)用,使代碼可讀性大大增強(qiáng)。于是我們就可以這樣創(chuàng)建Car類。

new Car.Builder().color(Color.BLUE)
                 .price(129800)
                 .pailiang("1.5T")
                 .brand("小鵬")
                 .build();

有沒(méi)有覺(jué)得創(chuàng)建過(guò)程一下子就變得那么清晰了。對(duì)應(yīng)的值是什么屬性一目了然,可讀性大大增強(qiáng)。

綜上,我們總結(jié)一下build模式的要點(diǎn):

1. 定義一個(gè)靜態(tài)內(nèi)部類Builder,內(nèi)部的成員變量和外部類一樣
2. Builder類通過(guò)一系列的方法用于成員變量的賦值,并返回當(dāng)前對(duì)象本身(this)
3. Builder類提供一個(gè)外部類的創(chuàng)建方法(build、create……),該方法內(nèi)部調(diào)用了外部類的一個(gè)私有構(gòu)造函數(shù),入?yún)⒕褪莾?nèi)部類Builder
4. 外部類提供一個(gè)私有構(gòu)造函數(shù)供內(nèi)部類調(diào)用,在該構(gòu)造函數(shù)中完成成員變量的賦值,取值為Builder對(duì)象中對(duì)應(yīng)的成變量的值

模式應(yīng)用廣泛

其實(shí)在Android中, Builder模式也是被大量的運(yùn)用。比如常見(jiàn)的對(duì)話框的創(chuàng)建

AlertDialog.Builder builder=new AlertDialog.Builder(this);
AlertDialog dialog=builder.setTitle("標(biāo)題")
 .setIcon(android.R.drawable.ic_dialog_alert)
 .setView(R.layout.myview)
 .setPositiveButton(R.string.positive, new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
 }
 })
 .setNegativeButton(R.string.negative, new DialogInterface.OnClickListener() {
 @Override
 public void onClick(DialogInterface dialog, int which) {
 }
 })
 .create();
dialog.show(); 

而且,各個(gè)第三方框架也大量的運(yùn)用了Builder模式
如Gson中的GsonBuilder,代碼太長(zhǎng)了,就不貼了,有興趣自己去看源碼,這里只貼出其Builder的使用方法。

GsonBuilder builder=new GsonBuilder();
Gson gson=builder.setPrettyPrinting()
 .disableHtmlEscaping()
 .generateNonExecutableJson()
 .serializeNulls()
 .create(); 

再看看著名的網(wǎng)絡(luò)請(qǐng)求框架OkHttp

Request.
Builder builder=new Request.Builder();
Request request=builder.addHeader("","")
 .url("")
 .post(body)
 .build();

總結(jié)

優(yōu)點(diǎn)

Builder模式通常作為配置類的構(gòu)建器將配置的構(gòu)建和表示分離開來(lái),同時(shí)也是將配置從目標(biāo)類中隔離出來(lái),避免作為過(guò)多的setter方法,并且隱藏內(nèi)部的細(xì)節(jié)。Builder模式比較常見(jiàn)的實(shí)現(xiàn)形式是通過(guò)鏈?zhǔn)秸{(diào)用,這樣使得代碼更加簡(jiǎn)潔、易懂。

缺點(diǎn)

內(nèi)部類與外部類相互引用,可能會(huì)導(dǎo)致內(nèi)存消耗比較大,不過(guò)鑒于現(xiàn)在的手機(jī)內(nèi)存來(lái)講,這點(diǎn)幾乎影響不大。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評(píng)論 6 543
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,520評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,541評(píng)論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,896評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評(píng)論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,062評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,608評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,356評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,555評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評(píng)論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,769評(píng)論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評(píng)論 1 295
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,289評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,516評(píng)論 2 379

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