文章摘要:
1出牧、設(shè)計(jì)模式的應(yīng)用在于其要達(dá)到的目的。
2歇盼、Adapter是適配器模式舔痕?策略模式?
3、Context是裝飾者模式嗎?
今天和小伙伴一起交流設(shè)計(jì)模式撵溃,有些心得,歡迎小伙伴拍磚~
一啸如、抽象工廠和工廠模式的異同點(diǎn)。
抽象工廠中有工廠方法的影子氮惯。抽象工廠需要獲取一系列對(duì)象的相關(guān)依賴叮雳,那么就需要定義一組接口,每個(gè)接口返回一個(gè)【對(duì)象依賴】筐骇。
1债鸡、相同點(diǎn):
- a、都是對(duì)象創(chuàng)建模式铛纬,即:都需要返回對(duì)象厌均。
- b、對(duì)于客戶端來說告唆,都封裝了創(chuàng)建對(duì)象的細(xì)節(jié)棺弊。
- c、擁有超類型父類擒悬,讓客戶端不需要關(guān)注創(chuàng)建的具體對(duì)象模她。
2、異同點(diǎn):
- a懂牧、返回對(duì)象數(shù)目侈净。工廠方法返回一個(gè)對(duì)象尊勿,抽象工廠返回對(duì)象的相關(guān)依賴集合。
在Android中Abstract Phone.java 是抽象超類型畜侦,其具體的子類中存在獲取getIccCard
元扔、CommandsInterface
、getCallTracker
等一系列Telphony相關(guān)對(duì)象依賴旋膳。從這個(gè)層面上來說澎语,這是一個(gè)抽象工廠。如果從單純的創(chuàng)建IccCard一個(gè)對(duì)象來說验懊,此就是工廠方法擅羞。
/**
* Returns the ICC card interface for this phone, or null
* if not applicable to underlying technology.
*/
public IccCard getIccCard() {
return null;
//throw new Exception("getIccCard Shouldn't be called from Phone");
}
/**
* Get call tracker
*/
public CallTracker getCallTracker() {
return null;
}
二、適配器模式
適配器模式類似動(dòng)畫片里的“變身/偽裝”技能义图,將自身偽裝成敵人减俏,從而混過敵人的耳目。 在Android中歌溉,適配器模式的使用垄懂,最常被大家提到的就屬于ListView和ListAdapter骑晶,但也要看怎么定位其工作流程:
- 1痛垛、策略模式的身影。我們通過ListView#setAdapter(ListAdapter adapter)來將adapter設(shè)定給ListView桶蛔,針對(duì)不同類型的數(shù)據(jù)源以及具體的使用場景匙头,adapter的實(shí)現(xiàn)類可以是ArrayAdapter、BaseAdapter仔雷、CursorAdapter蹂析,從這個(gè)層面來講,ListView和Adapter之間屬于策略模式碟婆。
設(shè)計(jì)原則:
針對(duì)超類型編程电抚,不要依賴具體實(shí)現(xiàn)。在ListView中竖共,ListAdapter屬于超類型蝙叛,對(duì)ListView來說不用去關(guān)心到底那個(gè)子類實(shí)> 現(xiàn)了ListAdapter。
- 2公给、模板方法的身影借帘。BaseAdapter是一個(gè)超類型類,繼承自ListAdapter淌铐。在BaseAdapter中肺然,存在
getDropDownView
、isEmpty
等模板算法骨架腿准,而將getView际起、getCount放到子類中去實(shí)現(xiàn)。{有點(diǎn)牽強(qiáng),不如Activity生命周期方法更生動(dòng)}
public View getDropDownView(int position, View convertView, ViewGroup parent) {
return getView(position, convertView, parent);
}
public boolean isEmpty() {
return getCount() == 0;
}
三街望、裝飾者模式
在跟小伙伴聊天的過程中倦沧,提到Context是不是裝飾者模式的一個(gè)應(yīng)用,我們也在這里產(chǎn)生了分歧它匕,從隱隱約約感覺是展融,但從小伙伴描述的工作流程來看,其敘述的工作流程并不是裝飾者模式豫柬。
裝飾者模式的目的在于為類增加功能告希、擴(kuò)展對(duì)象的行為,在這方面裝飾者模式提供了比繼承更有彈性的替代方案烧给。
那么Context在Android中的應(yīng)用是不是裝飾者模式的范例燕偶,我們從實(shí)現(xiàn)的角度來看下答案:
- 3.1、Context相關(guān)類對(duì)象介紹础嫡。Context對(duì)象是Abstract 超類型指么,其中包含了很多具體的Context對(duì)象的依賴,從這方面來說榴鼎,Context也是抽象工廠伯诬。
public abstract class Context {
public abstract Context getApplicationContext();
public abstract Resources getResources();
/** Return PackageManager instance to find global package information. */
public abstract PackageManager getPackageManager();
/** Return a ContentResolver instance for your application's package. */
public abstract ContentResolver getContentResolver();
/**
* Returns an AssetManager instance for the application's package.
* <p>
* <strong>Note:</strong> Implementations of this method should return
* an AssetManager instance that is consistent with the Resources instance
* returned by {@link #getResources()}. For example, they should share the
* same {@link Configuration} object.
*
* @return an AssetManager instance for the application's package
* @see #getResources()
*/
public abstract AssetManager getAssets();
}
ContextWrapper中有一個(gè)成員變量Context,通過attachBaseContext可以為其賦值巫财。
public class ContextWrapper extends Context {
Context mBase;
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
}
public class ContextThemeWrapper extends ContextWrapper {
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
}
}
- 3.2盗似、Context對(duì)象的創(chuàng)建。
PATH:frameworks/base/core/java/android/app/ActivityThread.java
在ActivityThread中平项,可以看到赫舒,Context對(duì)象來自ComtextImpl對(duì)象的實(shí)例化構(gòu)建。
private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
int displayId = Display.DEFAULT_DISPLAY;
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.token, displayId, r.overrideConfig);
appContext.setOuterContext(activity);
Context baseContext = appContext;
return baseContext;
}
- 3.2闽瓢、Activity的創(chuàng)建接癌。
首先:Activity繼承自ContextThemeWrapper。
其次:Activity是在ActivityThread.java中通過類裝載器創(chuàng)建的扣讼。
PATH:frameworks/base/core/java/android/app/ActivityThread.java
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
這個(gè)時(shí)候缺猛,就創(chuàng)建了一個(gè)Activity對(duì)象,也是一個(gè)Context對(duì)象届谈。
最后枯夜,調(diào)用attach方法,將Context傳入Activity中艰山。在Activity中湖雹,attachBaseContext就是上面ContextThemeWrapper的實(shí)現(xiàn)。
PATH:frameworks/base/core/java/android/app/ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
}
Activity.java
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window) {
attachBaseContext(context);
}
綜述:
我們?cè)贏ctivity中曙搬,直接通過Activity.this或者this來直接使用Activity的Context對(duì)象,這個(gè)Context對(duì)象其實(shí)就是ContextThemeWrapper摔吏,相比較于ContextImpl實(shí)例化對(duì)象鸽嫂,ContextThemeWrapper提供了對(duì)Theme主題的支持,讓Context對(duì)象的功能更加強(qiáng)大征讲。
從這個(gè)角度來說据某,Conetxt及其ContextThemeWrapper是裝飾者模式的應(yīng)用案例。