装饰模式也称为包装模式,其使用一种对客户端透明的方式来动态地扩展对象的功能,同时它也是继承关系的一种替代方案之一。在实际的开发中被广泛的运用,接下来我们就一起来看看吧!
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更加灵活
需要透明且动态地扩展类的功能时。
/**
* 抽象组件类
*/
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来完成的,这种就是典型的装饰模式的例子。