设计模式之装饰器模式

99 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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();
    }
}

总结

相对于其他设计模式,我认为装饰器模式相对比较好理解,类之间的关系也比较清晰。通过继承实现功能增强的操作可能我们在平时工作中已经用到过,只不过没有归纳到设计模式里。可能唯一稍微别扭的地方就是有一个装饰器的基类,如果我们只是有一个装饰类是体现不出这个基类的作用的,但是一旦装饰器增多,那这个基类装饰器可以很好地帮我们给装饰器分类,方便理解和维护。