設(shè)計(jì)模式是在日常的編程工作中對(duì)一些常見(jiàn)的問(wèn)題場(chǎng)景總結(jié)出來(lái)的最優(yōu)編程套路,通過(guò)這種抽象和總結(jié),可以在遇到類(lèi)似的需求時(shí)快速使用對(duì)應(yīng)的設(shè)計(jì)模式,實(shí)現(xiàn)高效優(yōu)雅的編程。在Android日常開(kāi)發(fā)中,我們也會(huì)經(jīng)常使用一些實(shí)用性強(qiáng),具有代表性的設(shè)計(jì)模式,對(duì)這些設(shè)計(jì)模式進(jìn)行了解和學(xué)習(xí),不僅有助于我們理解Android框架下的代碼,包括一些著名的開(kāi)源代碼的設(shè)計(jì)實(shí)現(xiàn)和使用,更有助于我們?cè)谧约旱木幊坦ぷ髦刑子眠@些模式,完成高質(zhì)量的編程。
本文將結(jié)合實(shí)例介紹其中一種常用的設(shè)計(jì)模式:Builder模式。
Builder模式主要用于復(fù)雜對(duì)象的構(gòu)造,通過(guò)使用Builder模式可以減少構(gòu)造器或方法調(diào)用傳入的參數(shù)數(shù)量。這對(duì)有很多個(gè)配置參數(shù)進(jìn)行初始化的對(duì)象來(lái)說(shuō)尤其適用。
以Android常用的圖片加載顯示工具Picasso為例,進(jìn)行初始化有十幾項(xiàng)可配置參數(shù),如果采用通常的set方法進(jìn)行設(shè)置,代碼看起來(lái)會(huì)是這樣:
Picasso picasso = new Picasso();
picasso.setDefaultBitmapConfig(Bitmap.Config.RGB_565);
picasso.setDownloader(new OkHttpDownloader(FileUtility.getPicassoCacheDir()))
picasso.setRequestTransformer(new Picasso.RequestTransformer() { ... })
picasso.setExecutor(executorService)
picasso.setMemoryCache(cache)
picasso.setListener(myListener)
picasso.setIndicatorsEnabled(true)
picasso.setLoggingEnabled(true)
或者采用多個(gè)參數(shù)的構(gòu)造函數(shù)的方式,像這樣:
Picasso picasso = new Picasso(Bitmap.Config.RGB_565,
new OkHttpDownloader(FileUtility.getPicassoCacheDir()),
new Picasso.RequestTransformer() { ... },
executorService,
cache,
myListener,
true,
true);
上面這兩種方式中,第一種set方式會(huì)產(chǎn)生很多重復(fù)的代碼,而且set方法的堆疊使代碼看起來(lái)比較亂;第二種多個(gè)參數(shù)的構(gòu)造函數(shù)的方式在參數(shù)眾多的情況下難以分清某個(gè)位置具體參數(shù)代表的意義,比如最后兩個(gè)boolean類(lèi)型的參數(shù)。而且如果只需要選擇性的初始化其中幾個(gè)變量,則需要添加多個(gè)接受不同參數(shù)的構(gòu)造函數(shù),或者使用這個(gè)構(gòu)造函數(shù),同時(shí)給不需要初始化的參數(shù)傳null,如下,顯然很不利于閱讀。
Picasso picasso = new Picasso(Bitmap.Config.RGB_565,
null,
new Picasso.RequestTransformer() { ... },
null,
null,
null,
true,
true);
使用Builder模式可以?xún)?yōu)雅的解決這個(gè)問(wèn)題。Builder模式包含兩部分,需要構(gòu)造的目標(biāo)類(lèi)和嵌套在該類(lèi)內(nèi)部的Builder類(lèi),通過(guò)兩步操作完成目標(biāo)類(lèi)的構(gòu)造:
- 通過(guò)Builder類(lèi)提供一系列函數(shù),接受各種設(shè)置,并存儲(chǔ)在Builder類(lèi)內(nèi)部。
- 所有配置都設(shè)置完成后,調(diào)用build函數(shù),利用Builder類(lèi)完成目標(biāo)類(lèi)的構(gòu)造。
具體代碼示例如下:
Picasso picasso = new Picasso.Builder(this)
.defaultBitmapConfig(Bitmap.Config.RGB_565)
.downloader(new OkHttpDownloader(FileUtility.getPicassoCacheDir()))
.requestTransformer(new Picasso.RequestTransformer() { ... })
.executor(executorService)
.memoryCache(cache)
.listener(myListener)
.indicatorsEnabled(true)
.loggingEnabled(true)
.build();
這種方式減少了很多重復(fù)的代碼,結(jié)構(gòu)清晰,每個(gè)配置的意義一目了然。我們看一下具體是怎么實(shí)現(xiàn)的,這里為了簡(jiǎn)化我們只選取了三個(gè)參數(shù)做演示,其他參數(shù)類(lèi)似:
public class Picasso {
final Cache cache;
boolean indicatorsEnabled;
boolean loggingEnabled;
...
Picasso(Context context, Cache cache, boolean indicatorsEnabled, boolean loggingEnabled);
public static class Builder {
private Cache cache;
private boolean indicatorsEnabled;
private boolean loggingEnabled;
...
public Picasso.Builder memoryCache(Cache memoryCache) {
this.cache = memoryCache;
return this;
}
public Picasso.Builder indicatorsEnabled(boolean enabled) {
this.indicatorsEnabled = enabled;
return this;
}
public Picasso.Builder loggingEnabled(boolean enabled) {
this.loggingEnabled = enabled;
return this;
}
public Picasso build() {
return new Picasso(context, this.cache, this.indicatorsEnabled, this.loggingEnabled);
}
}
可以看出,實(shí)現(xiàn)的原理很簡(jiǎn)單,Builder類(lèi)暫存了外界傳入的參數(shù),然后在build方法中,通過(guò)調(diào)用目標(biāo)類(lèi)的構(gòu)造函數(shù)完成對(duì)象的生成。下次遇到這種多項(xiàng)配置的初始化操作時(shí),你就可以嘗試用這種Builder模式,實(shí)現(xiàn)簡(jiǎn)潔優(yōu)雅的編程。