携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情
简介
装饰器模式的定义是:
是指在不改变现有对象结构的情况下,动态的给改对象增加一些职责(即增加其额外功能)的模式。
顾名思义就是对某个类进行装饰的模式,在不改变现有对象结构的情况下,对类的属性和方法进行装饰和拓展,让它拥有其他更丰富的功能。
既然不能改变原有的结构和功能,而要对其进行拓展,那不用怀疑就是要用继承来实现。通过继承原有的方法,然后对其进行增强。基本的思想和方法都已经确认了,那我们来看一个案例
案例
首先,我们定义一个接口类,一个抽象的动物类,有一个【叫】的方法
public interface Animal {
void speak();
}
然后定义一个狗子,实现【叫】的方法
public class Dog implements Animal {
@Override
public void speak() {
System.out.println("Dog wang wang");
}
}
定义一个鸭子,同样也实现【叫】方法
public class Duck implements Animal {
@Override
public void speak() {
System.out.println("Duck ga ga");
}
}
目前我们只定义2个实现类。这个时候如果我们有一个需求是要对能下蛋的动物增加输出一行【born egg】,那这个时候如果我们定义了不仅只有鸭子一种下蛋的动物,还有鸡子、大鹅、鸽子、鸵鸟等动物,那就得在每个类里去加了。有没有一种不修改动物实现类的方法来做到呢?
这个时候就轮到我们装饰器模式上场了。
增加一个装饰器的基类,即针对于动物的装饰器基类
public class AnimalDecorator implements Animal {
private Animal animal;
public AnimalDecorator(Animal animal) {
this.animal = animal;
}
@Override
public void speak() {
animal.speak();
}
}
大家看到这里是不是觉得已经可以满足需求了,我们只需要在AnimalDecorator类的speak方法中对speak进行增强,输出一行【born egg】即可。其实我觉得也可以,但是我们如果还有其他针对speak的装饰呢?那是不是又要定义一个,这样就针对一个方法的装饰就会有多个装饰类,这个时候就需要我们定义一个对speak装饰的基类,然后其他各种不通的增加去继承这个装饰基类就可以了。
注意此处网上大部分代码例子都有实现Animal接口的,但是我觉得完全可以不实现。或者我哪里理解出错了,请大佬指正。
所以我们继承AnimalDecorator来实现一个【生蛋】的装饰器
public class EggDecorator extends AnimalDecorator {
public EggDecorator(Animal animal) {
super(animal);
}
@Override
public void speak() {
super.speak();
jump();
}
private void jump() {
System.out.println("born egg");
}
}
应用类,对Duck实现生蛋的增强使用
public class App {
public static void main(String[] args) {
EggDecorator eggDecorator = new EggDecorator(new Duck());
eggDecorator.speak();
}
}
总结
相对于其他设计模式,我认为装饰器模式相对比较好理解,类之间的关系也比较清晰。通过继承实现功能增强的操作可能我们在平时工作中已经用到过,只不过没有归纳到设计模式里。可能唯一稍微别扭的地方就是有一个装饰器的基类,如果我们只是有一个装饰类是体现不出这个基类的作用的,但是一旦装饰器增多,那这个基类装饰器可以很好地帮我们给装饰器分类,方便理解和维护。