android開(kāi)發(fā)過(guò)程中,掌握常用的設(shè)計(jì)模式無(wú)疑會(huì)使我們的開(kāi)發(fā)效率大大的提高,最近面試的時(shí)候也常常被問(wèn)到開(kāi)發(fā)過(guò)程中都用到那些設(shè)計(jì)模式,于是決定收集些安卓開(kāi)發(fā)常用的設(shè)計(jì)模式作為儲(chǔ)備知識(shí)。
一:?jiǎn)卫J剑⊿ingleton Pattern)
概念:確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。
這樣做有以下幾個(gè)優(yōu)點(diǎn):
對(duì)于那些比較耗內(nèi)存的類,只實(shí)例化一次可以大大提高性能,尤其是在移動(dòng)開(kāi)發(fā)中。
保持程序運(yùn)行的時(shí)候該中始終只有一個(gè)實(shí)例存在內(nèi)存中
示例代碼:
private static RetrofitHelper instance;
/**
* 獲取單例
*/
public static RetrofitHelper getInstance() {
if (null == instance) {
synchronized (RetrofitHelper.class) {
if (null == instance) {
instance = new RetrofitHelper();
}
}
}
return instance;
}
要保證單例,需要做一下幾步
- 必須防止外部可以調(diào)用構(gòu)造函數(shù)進(jìn)行實(shí)例化,因此構(gòu)造函數(shù)必須私有化。
- 必須定義一個(gè)靜態(tài)函數(shù)獲得該單例
- 單例使用volatile修飾
- 使用synchronized 進(jìn)行同步處理,并且雙重判斷是否為null,我們看到synchronized (Singleton.class)里面又-進(jìn)行了是否為null的判斷,這是因?yàn)橐粋€(gè)線程進(jìn)入了該代碼,如果另一個(gè)線程在等待,這時(shí)候前一個(gè)線程創(chuàng)建了一個(gè)實(shí)例出來(lái)完畢后,另一個(gè)線程獲得鎖進(jìn)入該同步代碼,實(shí)例已經(jīng)存在,沒(méi)必要再次創(chuàng)建,因此這個(gè)判斷是否是null還是必須的。
單例模式在其他地方的應(yīng)用:
初始化Android-Universal-Image-Loader,EventBus,Rxbus,ActivityManager 中
二:建造者模式(Builder Pattern)
概念:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的展示。
示例代碼:
new MaterialDialog.Builder(activity)
.title(describe+phone)//TextConvertUtils.getFormatPhone(servePhone)
.positiveText(R.string.cancel)
.negativeText(call)
.onNegative(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
Intent intent = null;
intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + finalPhone));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.startActivity(intent);
}
}).show();
用了這么久的Dialog,也是剛知道這是Builder模式...
還有Retrofit,OkHttp中OkHttpClient的創(chuàng)建都是....
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ConfingIp.onLineIp)
.client(getOkHttpClient())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.cache(getCache())
.addInterceptor(new HttpCacheInterceptor())
.addInterceptor(new LogInterceptor())
.addNetworkInterceptor(new HttpRequestInterceptor())
.build();
還有okhttp的Request,Response也是通過(guò)Builder模式創(chuàng)建的,還有很多...
三:觀察者模式(Observer Pattern)
概念:定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)送改變時(shí),所有依賴于它的對(duì)象都能得到通知并被自動(dòng)更新
示例代碼:
Button baiduclickButton = (Button)findViewById(R.id.button1);
//注冊(cè)觀察者
baiduclickButton.setOnClickListener(new OnClickListener()
{
//觀察者實(shí)現(xiàn)
@Override
public void onClick(View arg0)
{
Log.d("Mythou_Log", "Click the button ");
}
});
安卓中按鈕的點(diǎn)擊監(jiān)聽(tīng)無(wú)疑是最常見(jiàn)的觀察者模式,這里實(shí)際上是應(yīng)用了一對(duì)一的觀察者模式,setOnClickListener()方法就是注冊(cè)一個(gè)觀察者,Button對(duì)象就是我們要觀察的目標(biāo)對(duì)象。而new出來(lái)的OnClickListener(),就是我們實(shí)際的觀察者。
我了解觀察者模式的時(shí)候應(yīng)該是學(xué)習(xí)RxJava時(shí)候,Rxjav,EventBus,RxBus使用的都是觀察者模式;
//注冊(cè)EventBus,在接收消息的頁(yè)面注冊(cè)
EventBus.getDefault().register(this);
mBtnFirst.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//發(fā)送消息
EventBus.getDefault().post(new FirstEvent("First ,咻咻咻...."));
}
});
//接收消息
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventMainThread(FirstEvent event) {
Log.e("onMessageEventMainThread", Thread.currentThread().getName());
}
這里是EventBus的Demo,我用的是RxBus就不copy了
四:策略者模式(Strategy Pattern)
概念:策略模式定義了一些列的算法,并將每一個(gè)算法封裝起來(lái),而且使它們還可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變換。
關(guān)于策略者模式的概念如何理解,個(gè)人認(rèn)為這篇文章解釋的很好:策略模式:網(wǎng)絡(luò)小說(shuō)的固定套路
我在安卓開(kāi)發(fā)過(guò)程中應(yīng)用的策略者模式很少,但還是有一些的。
listView.setAdapter(),里面的Adapter ,一般都是自定義的Adapter ,繼承自BaseAdapter ,這就是典型的策略模式,當(dāng)ListView 的Item呈現(xiàn)不同形式,在getView方法中,就得不同的實(shí)現(xiàn)。
/**
* 判斷是普通的item視圖還是footerview視圖
*
* @param position
* @return
*/
@Override
public int getItemViewType(int position) {
if (position + 1 == getItemCount()) {//最后一個(gè)item設(shè)置為footerview
return TYPE_FOOTER;
} else {
return TYPE_ITEM;
}
}
我也是剛剛知道這是策略者模式,雖然現(xiàn)在還不能靈活的把策略者模式運(yùn)用在其他地方....
五:適配器模式(Adapter Pattern)
概念:把一個(gè)類的接口轉(zhuǎn)換為客戶端所期待的另一種接口,從而使原本因接口不匹配而無(wú)法再一起工作的兩個(gè)類能夠在一起工作。
android中ListView與Adapter的應(yīng)用就是典型的適配器模式,
示例代碼:
省略
適配器模式原理參考:適配器模式在android中的應(yīng)用
應(yīng)該我太菜,不長(zhǎng)使用設(shè)計(jì)模式,暫時(shí)就想到這些了。
最后了解更多的安卓開(kāi)發(fā)中的應(yīng)用的設(shè)計(jì)模式:專題:Android 開(kāi)發(fā)設(shè)計(jì)模式系列集錦