Context装饰者模式
Context
Context 类在 Android 中被称为“上帝对象”,它本质是一个抽象类,其在我们装饰者模式里相当于抽象组件,而在其内部定义了大量的抽象方法,比如我们经常会用到的 startActivity 方法。
...
public abstract void startActivity(@RequiresPermission Intent intent);
...
public abstract void startActivity(@RequiresPermission Intent intent,
@Nullable Bundle options);
...
真正的实现是在 ContextImpl 中完成的,ContextImpl 继承自 Context 抽象类,并实现了 Context 中的抽象方法。
@Override
public void startActivity(Intent intent) {
warnIfCallingFromSystemProcess();
startActivity(intent, null);
}
这里 ContextImpl 就相当于组件具体实现类,那么谁来承担装饰者的身份呢?
Activity 从类层次上来说本质是一个 Context。Activity 并非直接继承于 Context,而是继承于 ContextThemeWrapper。
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback,
AutofillManager.AutofillClient {
...
}
而这个 ContextThemeWrapper 又是继承于 ContextWrapper。
public class ContextThemeWrapper extends ContextWrapper {
...
}
最终这个 ContextWrapper 才继承于 Context。
为什么类层次会这么复杂呢?其实这里就是一个典型的装饰模式,ContextWrapper 就是我们要找的装饰者,在 ContextWrapper 中有一个 Context 的引用。
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
/**
* Set the base context for this ContextWrapper. All calls will then be
* delegated to the base context. Throws
* IllegalStateException if a base context has already been set.
*
* @param base The new base context for this wrapper.
*/
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
...
ContextWrapper 类的 startActivity 方法如下:
@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent);
}
可以看出它调用了 ContextImpl 中对应的方法。
装饰模式应用的套路都是很相似的,对于具体方法的包装扩展则由 ContextWrapper 的具体子类完成,比如我们的 Activity、Service 和 Application。