動態地給一個對象添加一些額外的職責。裝飾模式比子類就增長功能來講更爲靈活。java
定義了一個接口,定義了一個sing的方法bash
public interface Component {
void sing();
}
複製代碼
定義了具體的被裝飾者,實現了Component接口app
public class ConcreteComponent implements Component {
@Override
public void sing() {
System.out.print("sing....");
}
}
複製代碼
定義了抽象裝飾者,內部持有被裝飾者的引用,才能操做被裝飾者ide
public abstract class Decorator implements Component {
private Component mComponent;
public Decorator(Component component) {
this.mComponent = component;
}
@Override
public void sing() {
mComponent.sing();
}
}
複製代碼
定義了具體的裝飾者,能夠在方法內作一些功能擴展的工做。ui
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
//先交錢,後唱歌(添加了收費的功能)
@Override
public void sing() {
System.out.print("先交錢....");
super.sing();
}
}
複製代碼
public class DecoratorTest {
public static void main(String[] args){
Component component = new ConcreteComponent();
Decorator decorator = new ConcreteDecorator(component);
decorator.sing();
}
}
複製代碼
public class ConcreteDecorator2 extends Decorator{
public ConcreteDecorator2(Component component) {
super(component);
}
@Override
public void sing() {
System.out.print("奏樂....");
super.sing();
}
}
複製代碼
public class DecoratorTest {
public static void main(String[] args){
Component component = new ConcreteComponent();
Decorator decorator = new ConcreteDecorator2(component);
decorator.sing();
}
}
複製代碼
更換了一個裝飾者,提供了一些其餘功能,方便裝飾者的更換。this
public abstract class Context {
......
public abstract void startActivity(Intent var1);
public abstract void startActivity(Intent var1, @RecentlyNullable Bundle var2);
......
}
複製代碼
Context做爲抽象基本,定義了四大組件啓動、獲取資源、類加載、文件管理、權限管理等等抽象方法spa
class ContextImpl extends Context {
......
@Override
public void startActivities(Intent[] intents, Bundle options) {
warnIfCallingFromSystemProcess();
if ((intents[0].getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
throw new AndroidRuntimeException(
"Calling startActivities() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag on first Intent."
+ " Is this really what you want?");
}
mMainThread.getInstrumentation().execStartActivities(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity) null, intents, options);
}
......
}
複製代碼
ContextImpl做爲被裝飾者,內部定義了Activity啓動等方法的具體實現code
public class ContextWrapper extends Context {
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
//獲取被裝飾者ContextImpl的引用
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
......
@Override
public void startActivities(Intent[] intents) {
mBase.startActivities(intents);
}
@Override
public void startActivities(Intent[] intents, Bundle options) {
//內部調用的仍是ContextImpl的方法
mBase.startActivities(intents, options);
}
......
}
複製代碼
ContextWrapper做爲裝飾者的基類,持有被裝飾者ContextImpl的引用,並在自身的方法內部調用ContextImpl中的邏輯component
ActivityThread:orm
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
......
}
複製代碼
經過調用LoadedApk的makeApplication方法建立了Application實例對象。
LoadedApk:
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
......
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
......
}
複製代碼
建立了被裝飾者ContextImpl對象,而後調用了Instrumentation的newApplication方法建立了Application。
Instrumentation:
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
複製代碼
經過調用Application(裝飾者)的attach方法,將ContextImpl對象傳入。
final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
複製代碼
經過調用裝飾基類ContextWrapper的attachBaseContext方法來將ContextImpl對象傳入,而後對被裝飾者進行操做。
ActivityThread:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
......
//(1)建立了ContextImpl
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//(2) 建立Activity對象
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
......
if (activity != null) {
appContext.setOuterContext(activity);
//(3)將ContextImpl傳入到Activity中
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, r.configCallback);
......
return activity;
}
}
}
複製代碼
調用了Activity的attach方法: Activity:
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, ActivityConfigCallback activityConfigCallback) {
attachBaseContext(context);
......
}
複製代碼
完成了ContextImpl的建立,並傳入到Activity中
Service的啓動最後調用到了ActivityThread的handleCreateService方法 ActivityThread:
private void handleCreateService(CreateServiceData data) {
......
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
//(1)service建立
service = (Service) cl.loadClass(data.info.name).newInstance();
......
//(2)ContextImpl建立
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
//(3)ContextImpl傳入
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
service.onCreate();
......
}
}
複製代碼
Service:
public final void attach(
Context context,
ActivityThread thread, String className, IBinder token,
Application application, Object activityManager) {
attachBaseContext(context);
......
}
複製代碼
完成了Service建立和ContextImpl的傳入