设计模式之装饰模式

前言

为什么要写装饰模式?这几天在工作中又遇到了RePlugin。在RePlugin中有插件和宿主的概念,插件和宿主分别有自己的Context。通过以下两个方法可以分别获得宿主和插件的Context。

RePlugin是一套完整的、稳定的、适合全面使用的,占坑类插件化方案,由360手机卫士的RePlugin Team研发,也是业内首个提出”全面插件化”(全面特性、全面兼容、全面使用)的方案。

1
2
RePlugin.getHostContext();
RePlugin.getPluginContext();

于是笔者读了以上两个方法的源码,进而读了一下Context类的部分源码和继承关系。看到有关Context类中使用了装饰模式。故而打算写一篇介绍装饰模式的文章,下一篇文章会再介绍Context的继承结构,以及在RePlugin中两个Context是如何得到的。

什么是装饰模式

装饰模式(Decorator Pattern)又叫包装模式,它是结构型模式的一种。装饰模式可以动态的给对象添加一些额外的职责,它比继承更加灵活。如何理解这种灵活性?笔者认为通过继承的方式添加一些功能,必然要改动子类。但是使用装饰模式,可以通过新增一个装饰类而不必修改之前的代码。

装饰模式的结构图

1.png

装饰模式包含如下角色:

  • Component: 抽象组件。定义一个抽象类或接口。
  • ConcreteComponent: 具体组件。即被装饰者,给这个类的对象添加一些职责。
  • Decorator: 抽象装饰类。
  • ConcreteDecorator: 具体装饰类。给组件添加职责。

装饰模式实现

下面按照装饰模式的结构图来实现一下装饰模式

1. 定义抽象组件 Component
1
2
3
public abstract class Component {
public abstract void operation();
}
2. 定义具体组件(被装饰者) ConcreteComponent
1
2
3
4
5
6
7
8
9
public class ConcreteComponent extends Component {

@Override
public void operation() {

System.out.println("被装饰对象");
}

}
3. 定义抽象装饰类 Decorator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public abstract class Decorator extends Component {

protected Component component;

public Decorator(Component component) {
this.component = component;
}

@Override
public void operation() {
if (component != null) {
component.operation();
}
}
}
4. 定义具体装饰类,这里定义两个ConcreteDecoratorA和ConcreteDecoratorB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ConcreteDecoratorA extends Decorator {

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

@Override
public void operation() {
super.operation();

addDecoratorA("A");
}

private void addDecoratorA(String decorator) {
System.out.println("给对象装饰" + decorator);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ConcreteDecoratorB extends Decorator {

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

@Override
public void operation() {
super.operation();

addDecoratorB("B");
}

private void addDecoratorB(String decorator) {
System.out.println("给对象装饰" + decorator);
}
}

这样装饰模式的实现就完成了,接下来调用一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


ConcreteComponent component = new ConcreteComponent();

ConcreteDecoratorA decoratorA = new ConcreteDecoratorA(component);

ConcreteDecoratorB decoratorB = new ConcreteDecoratorB(component);

decoratorA.operation();

decoratorB.operation();
}
}

打印输出结果:

1
2
3
4
I/System.out: 被装饰对象
I/System.out: 给对象装饰A
I/System.out: 被装饰对象
I/System.out: 给对象装饰B

可以看到ConcreteComponent此时已经具有了A和B的功能,同时ConcreteComponent 并不知道ConcreteDecoratorAConcreteDecoratorB 的存在。当我们要给ConcreteComponent增加其他功能,可以在不改变原有代码的前提下,动态的扩展ConcreteComponent的功能,只需要给ConcreteComponent增加新的装饰类即可。当然装饰模式也有一个小小的缺点,就是它会增加代码的复杂性。可根据实际情况选择是否使用装饰模式。

demo地址:https://github.com/77Y/Decorator