android设计模式之装饰模式(二)

本文深入探讨了Android中装饰模式的应用,以Context类为例,详细解释了抽象组件、具体组件及装饰者的角色扮演,并通过源码展示了如何通过装饰模式扩展功能。

android源码中的装饰模式其实我们会经常接触到,只是我们并不知道这是装饰模式实现的,Context类在android中被称为“上帝对象”,他本质是一个抽象类,在我们装饰模式里就相当于抽象组件,即被装饰对象,context在其内部定义了大量的抽象方法,比如我们经常用到的startActivity方法,下面我们看看context类的源码:

public abstract class Context {
	//省略一些方法和属性定义......

	//启动一个Activity
	public abstract void startActivity(Intent intent);

	//启动一个Activity
	public abstract void startActivity(Intent intent, Bundle options);

	//启动多个Activity
	public abstract void startActivities(Intent[] intents);
	
	//启动多个Activity
	public abstract void startActivities(Intent[] intents, Bundle options);
	
	//获取应用程序信息
	public abstract ApplicationInfo getApplicationInfo();
	
	//启动一个Service
	public abstract ComponentName startService(Intent service);
	
	//发送一个广播
	public abstract void sendBroadcast(Intent intent);
	
	//发送一个广播
	public abstract void sendBroadcast(Intent intent,
			String receiverPermission);
	
	//发送一个有序广播
	public abstract void sendOrderedBroadcast(Intent intent,
			String receiverPermission, BroadcastReceiver resultReceiver,
			Handler scheduler, int initialCode, String initialData,
			Bundle initialExtras);
	
	//获取主线程中的Looper
	public abstract Looper getMainLooper();
	
	//获取应用级的context对象
	public abstract Context getApplicationContext();
	
	//获取相应的系统服务对象
	public abstract Object getSystemService(String name);
	
	//获取外部文件存储目录
	public abstract File getExternalFilesDir(String type);
	
	//获取resources对象处理资源文件
	public abstract Resources getResources();
	
	//省略若干抽象方法的定义代码
}
Context类中的方法均为抽象方法,而真正的实现是在ContextImpl中完成的,ContextImpl继承自Context抽象类,并实现了他的抽象方法,具体代码如下:

class ContextImpl extends Context {
	//省略若干代码.......
	@Override
	public void startActivity(Intent intent) {
		warnIfCallingFromSystemProcess();
		startActivity(intent, null);
	}

	/** @hide */
	@Override
	public void startActivityAsUser(Intent intent, UserHandle user) {
		startActivityAsUser(intent, null, user);
	}

	@Override
	public void startActivity(Intent intent, Bundle options) {
		warnIfCallingFromSystemProcess();
		if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
			throw new AndroidRuntimeException(
					"Calling startActivity() from outside of an Activity "
							+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
							+ " Is this really what you want?");
		}
		mMainThread.getInstrumentation().execStartActivity(
				getOuterContext(), mMainThread.getApplicationThread(), null,
				(Activity) null, intent, -1, options);
	}
	//省略若干代码.......
	@Override
	public void sendBroadcast(Intent intent, String receiverPermission) {
		warnIfCallingFromSystemProcess();
		String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
		String[] receiverPermissions = receiverPermission == null ? null
				: new String[] {receiverPermission};
		try {
			intent.prepareToLeaveProcess();
			ActivityManagerNative.getDefault().broadcastIntent(
					mMainThread.getApplicationThread(), intent, resolvedType, null,
					Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
					null, false, false, getUserId());
		} catch (RemoteException e) {
			throw new RuntimeException("Failure from system", e);
		}
	}
	//省略若干代码.......
}
这里ContextImpl就相当于组件具体实现类,那么谁来承担装饰着的身份呢?我们知道Activity 从类层次上来说本质是一个Context,如果大家留意过Activity源码会发现它并非直接继承于Context,而是继承于ContextThemeWrapper.

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback {
        //省略若干代码......
        
}
//而这个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;
    }
    //省略若干代码.......
    
}

/**
 *其实到现在我们就能看出一点装饰模式的结构了,但好像还缺一个来自抽象组件的方法
 *同样我们只看一下startActivity,在ContextWrapper中同样有一个startActivity方法。
 */
 
public class ContextWrapper extends Context {
   //省略若干代码.......
    
    @Override
    public void startActivity(Intent intent){
        mBase.startActivity(intent);
    }
    //省略若干代码.......
    
    @Override
    public void startActivity(Intent intent,Bundle options){
        mBase.startActivity(intent,options);
    }
    //省略若干代码......
    
}
这里可以看到ContextWrapper中的startActivity方法也仅仅是简单的调用了具体组件实现类ContextImpl中的方法而已,其实ContextWrapper中的所有方法都是仅仅调用ContextImpl的对应方法,这就和我们讲的装饰模式的结构非常类似了,装饰模式应用的结构都很相似,对于具体方法的包装扩展则由ContextWrapper 的具体字累完成,比Activity,Service,和Application。这三个类的方法不在细说,大家自行查看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值