装饰模式(Decorator Pattern)
Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.
装饰模式用来给子类动态的添加功能,它是继承的补充。还是以代码来举例:
1abstract class JobCls {
2 abstract execute(): void;
3}
4
5class Job extends JobCls {
6 execute() {
7 console.log("execute job");
8 }
9}
10
11class SendBeforeLog extends JobCls {
12 constructor(public job: Job) {
13 super();
14 }
15
16 execute() {
17 this.executeBafore();
18 this.job.execute();
19 }
20
21 executeBafore() {
22 console.log('job will execute');
23 }
24}
25
26class SendAfterLog extends JobCls {
27 constructor(public job: Job) {
28 super();
29 }
30
31 execute() {
32 this.job.execute();
33 this.executeAfter();
34 }
35
36 executeAfter() {
37 console.log('job executed');
38 }
39}
40
41let job = new Job();
42job = new SendBeforeLog(job);
43job = new SendAfterLog(job);
44
45job.execute();
在最基础的Job类中,execute方法已经是原子的了,无法再继续拆分。那么使用装饰模式对其进行功能的添加是一个非常好的方法。上面的代码中有两个装饰类:SendBeforeLog与SendAfterLog,分别对Job运行前后增加功能。在最后的execute执行时,会依次显示出所有console。
也许你会问,我直接Job类的源代码不就好了,那么在有大量同类的情况下,难道还要一个个修改代码么?此时使用装饰模式就是最好的方法。当大量逻辑需要添加同一个功能时,装饰模式是一个不错的选择。
装饰模式最为继承的补充,装饰方法和被装饰方法相互独立,装饰方法无论套用了多少次装饰类,最终仍会执行原本的逻辑。
但装饰模式也有个很大的缺点,就是比较复杂,而且装饰的顺序是固定的,那么在有多层装饰类嵌套时,可能需要阅读源代码才能确定执行顺序,除非所有装饰类执行的顺序是相同的。