Android进阶之路Android技术知识Android开发

Android 设计模式 - 装饰器模式

2019-03-01  本文已影响6人  Android架构

简介

在现实生活中可以看到很多装饰模式的例子,或者可以大胆的说装饰模式无处不在,就拿人来说,人需要各式各样的衣着,不管你穿着怎样,但是对于人的本质来说是不变的,充其量只是在外面披上一层遮羞物而已,这就是装饰模式,装饰物各不相同但是对象的本质是不变的.它的uml类图如下:

装饰模式的简单实现

人总是要穿衣服,我们将人定义为一个抽象类,将其穿衣服的行为定义为一个抽象方法,show me the code.

public abstract class Person {
    /**
     * person下有一个穿着的抽象方法
     */
    public abstract void dressed();
}

public class Boy extends Person{
    @Override
    public void dressed() {
        System.out.println("穿了内衣内裤");
    }
}

PersonCloth用来装饰Person

public abstract class PersonCloth extends Person{

    protected Person mPerson;   //保持一个Person类的引用

    public PersonCloth(Person person) {
        mPerson = person;
    }

    @Override
    public void dressed() {
        mPerson.dressed();
    }
}

下面两个是继承PersonCloth的实际装饰类

public class CheapCloth extends PersonCloth{
    public CheapCloth(Person person) {
        super(person);
    }

    public void dressShorts(){
        System.out.println("穿条短裤");
    }

    @Override
    public void dressed() {
        super.dressed();
    }
}

public class ExpensiveCloth extends PersonCloth{
    public ExpensiveCloth(Person person) {
        super(person);
    }

    /**
     * 穿短袖
     */
    private void dressShirt(){
        System.out.println("穿件短袖");
    }

    /**
     * 穿皮衣
     */
    private void dressLeather(){
        System.out.println("穿件皮衣");
    }

    /**
     * 穿牛仔裤
     */
    private void dressJean(){
        System.out.println("穿条牛仔裤");
    }

    @Override
    public void dressed() {
        super.dressed();
        dressShirt();
        dressLeather();
        dressJean();
    }
}

最终调用

public class Main {
    public static void main(String[] args){
        //首先我们要有一个Boy
        Person person = new Boy();

        //穿上便宜的衣服
        CheapCloth cheapCloth = new CheapCloth(person);
        cheapCloth.dressed();

        //穿上昂贵的衣服
        ExpensiveCloth expensiveCloth = new ExpensiveCloth(person);
        expensiveCloth.dressed();
    }
}

Android源码中的装饰模式

在Android中Context常常被称为上帝对象,Context中定义了大量的抽象方法,如下

//....代码省略...
public abstract void startActivity(@RequiresPermission Intent intent);
public abstract void startActivity(@RequiresPermission Intent intent,
            @Nullable Bundle options);
//....代码省略...

而Context的真正实现其实是在ContextImpl中完成,ContextImpl继承自Context抽象类,并实现了Context的抽象方法.

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

        // Calling start activity from outside an activity without FLAG_ACTIVITY_NEW_TASK is
        // generally not allowed, except if the caller specifies the task id the activity should
        // be launched in.
        if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
                && options != null && ActivityOptions.fromBundle(options).getLaunchTaskId() == -1) {
            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);
    }
//....代码省略...
}

ContextImpl其实承担的是组件的身份,那么谁来承担装饰者的身份呢,其实只要继承自ContextThemeWrapper的组件都是装饰者的身份,例如Activity.

public class Activity extends ContextThemeWrapper

ContextThemeWrapper又继承ContextWrapper

public class ContextWrapper extends Context {
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }
}

其实看到这里已经可以看到一些装饰者模式了,ContextWrapper的startActivity其实就是调用的mBase,而mBase实际上就是ContextImpl的实例.

@Override
    public void startActivity(Intent intent) {
        mBase.startActivity(intent);
    }

总结

装饰模式常常会和代理模式混淆,我们来说说这两者的区别,装饰模式是对对象功能的扩展,是继承关系的一种替代方案(比继承更加灵活),而代理模式则是给一个对象提供一个代理对象,并有代理对象来控制原有对象的引用。
装饰模式应该为所有装饰的对象增强功能;代理模式对代理的对象施加控制,但不对对象本身的功能进行增强
【附录】

资料图

需要资料的朋友可以加入Android架构交流QQ群聊:513088520

点击链接加入群聊【Android移动架构总群】:加入群聊

获取免费学习视频,学习大纲另外还有像高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)等Android高阶开发资料免费分享。

上一篇下一篇

猜你喜欢

热点阅读