一, 基本概念:
1, 定义:
动态地给一个对象添加一些额外的职责. 装饰模式比子类就增加功能来说更为灵活.
2, 应用场景:
需要扩展一个类的功能.
动态的为一个对象增加功能, 而且还能动态撤销.
3, 通用类图:
Component: 抽象类或者接口, 这是装饰者和被装饰者都需要实现的接口或者继承的基类.
ConcreteComponent: 被装饰者的具体构件
Decorate: 装饰者角色, 一般是一个抽象类, 定义一个 private 变量指向 Component.
ConcreteDecotator: 装饰者具体实现类, 一些在方法中实现一些功能的添加
二, 示例:
1,Component:
定义了一个接口, 定义了一个 sing 的方法
- public interface Component {
- void sing();
- }
2,ConcreteComponent:
定义了具体的被装饰者, 实现了 Component 接口
- public class ConcreteComponent implements Component {
- @Override
- public void sing() {
- System.out.print("sing....");
- }
- }
3,Decorator:
定义了抽象装饰者, 内部持有被装饰者的引用, 才能操作被装饰者
- public abstract class Decorator implements Component {
- private Component mComponent;
- public Decorator(Component component) {
- this.mComponent = component;
- }
- @Override
- public void sing() {
- mComponent.sing();
- }
- }
4,ConcreteDecorator:
定义了具体的装饰者, 可以在方法内做一些功能扩展的工作.
- public class ConcreteDecorator extends Decorator {
- public ConcreteDecorator(Component component) {
- super(component);
- }
- // 先交钱, 后唱歌 (添加了收费的功能)
- @Override
- public void sing() {
- System.out.print("先交钱....");
- super.sing();
- }
- }
5, 使用:
- public class DecoratorTest {
- public static void main(String[] args){
- Component component = new ConcreteComponent();
- Decorator decorator = new ConcreteDecorator(component);
- decorator.sing();
- }
- }
6, 更换装饰者:
- 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();
- }
- }
更换了一个装饰者, 提供了一些其他功能, 方便装饰者的更换.
三, Context 中的装饰模式
1,Context 相关类图:
Context 对应的是装饰者和被装饰者都需要继承的抽象类
ContextWrapper 对应的是装饰者的基类
ContextImpl 对应的是被装饰者, 一些逻辑的真正处理的类
Activity,Service,Application 对应的是装饰者的具体实现类
- 2,Context
- public abstract class Context {
- ......
- public abstract void startActivity(Intent var1);
- public abstract void startActivity(Intent var1, @RecentlyNullable Bundle var2);
- ......
- }
Context 作为抽象基本, 定义了四大组件启动, 获取资源, 类加载, 文件管理, 权限管理等等抽象方法
- 3,ContextImpl
- 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 启动等方法的具体实现
- 4,ContextWrapper:
- 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 中的逻辑
5,Application Context 创建:
- ActivityThread:
- 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 对象传入, 然后对被装饰者进行操作.
6,Activity Context 的创建:
- 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, Windows, 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,
- Windows Windows, ActivityConfigCallback activityConfigCallback) {
- attachBaseContext(context);
- ......
- }
完成了 ContextImpl 的创建, 并传入到 Activity 中
7,Service Context 的创建
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 的传入
来源: https://juejin.im/post/5c9b2bf56fb9a070e937d1f2