装饰设计模式

           装饰模式也称为包装模式,其使用一种对客户端透明的方式来动态地扩展对象的功能,同时它也是继承关系的一种替代方案之一。在实际的开发中被广泛的运用,接下来我们就一起来看看吧!

 

定义:

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更加灵活

 

使用场景:

需要透明且动态地扩展类的功能时。

 

小事例:         

/**
 * 抽象组件类
 */
public abstract class Component {

    public abstract void operate();

}
/**
 * 具体实现类
 */
public class ConcreteComponent extends Component {
    @Override
    public void operate() {
        // TODO 具体逻辑处理地方
    }
}
/**
 * 抽象装饰者
 */
public abstract class Decorator extends Component {

    // 持有一个Component对象的引用
    private Component component;

    // 必要的构造方法,需要一个Component类型的对象
    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operate() {
        component.operate();
    }
}
public class ConcreteDecorator extends Decorator {

    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operate() {
        operateA();
        super.operate();
    }


    public void operateA() {

    }
}

简要解释一下:

Component:抽象组件。可以是一个接口或抽象类,其充当的就是被装饰的原始对象。

ConcreteComponent:组件具体实现类。该类是Component类的基本实现,也是我们装饰的具体对象。

Decorator:抽象装饰者。其承担的职责就是为了装饰我们的组件对象,其内部一定要有一个指向组件对象的引用。

ConcreteDecoratorA:装饰者具体实现类

下面配一张图更好去理解上面的东西:

源码分析:

在源码当中,Context类被称为“上帝对象”,它本质是一个抽象类,其在我们装饰模式里面就相当于抽象组件,而在其内部定义了大量的抽象方法

public abstract class Context{
        
    // 省略代码
    
    public abstract void startActivity(@RequiresPermission Intent intent);

    public abstract void startActivity(@RequiresPermission Intent intent,
            @Nullable Bundle options);


    // 省略代码
}
​

而其真正的实现是在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();    
        final int targetSdkVersion = getApplicationInfo().targetSdkVersion;

        if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
                && (targetSdkVersion < Build.VERSION_CODES.N
                        || targetSdkVersion >= Build.VERSION_CODES.P)
                && (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就相当于组件具体实现类,那么谁来承担装饰者的身份呢?我们知道Activity从类层次上来说本质是一个Context,但是我们的Activity并非直接继承于Context,而是继承于ContextThemeWrapper,而这个ContextThemeWrapper又是继承于ContextWrapper,最后ContextWrapper继承于Context。为什么Activity的类层次会这么复杂呢?其实这里就是一个典型的装饰模式,ContextWrapper就是我们要找的装饰者,我们发现在ContextWrapper中有一个Context的引用

​

public class ContextWrapper extends Context{

    Context mBase;

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

    // 省略代码
 
    @Override
    public void startActivity(Intent intent) {
        mBase.startActivity(intent);
    }

    // 省略代码 

}

​

而其实我们最后的startActivity是由ContextImpl来完成的,这种就是典型的装饰模式的例子。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值