Decorator - 装饰器设计模式

96 阅读2分钟

什么是装饰者模式?

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。装饰类和扩展类不会耦合,可以替代继承关系。

优缺点

优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点:多层装饰比较复杂。

示例

我们可以类比一下流行游戏王者荣耀,每个英雄都会有很多套皮肤,带着皮肤可以有更绚丽的外观,更俏皮的语音,但是英雄的技能,定位,玩法不会发生任何变化。我们可以把皮肤就理解为装饰类,英雄本体就是被装饰类。


interface Movable {
    void move();
}

class Hero implements Movable {
    private String name;
    public Hero(String name) {
        this.name = name;
    }
    @Override
    public void move() {
        System.out.println(this.name + "走起来了。。。");
    }

    public String getName() {
        return this.name;
    }
}

// 声明抽象类的装饰器方便扩展
abstract class HeroDecorator implements Movable {
    protected Hero hero;
    public HeroDecorator(Hero hero) {
        this.hero = hero;
    }
}

// 声明一个具体的装饰器来继承 HeroDecorator
class NikeShoesHero extends HeroDecorator {
    public NikeShoesHero(Hero hero) {
        super(hero);
    }
    // 子类增强既有的接口
    @Override
    public void move() {
        System.out.print("穿上布灵布灵的耐克鞋,");
        hero.move();
    }
    // 子类增强的新方法
    public void pose() {
        System.out.println(hero.getName() + "摆了个Pose并说Just Do It!");
    }
}

最后我们写个测试类:

public static void main(String[] args) {
    final Hero hero = new Hero("亚瑟");
    System.out.println("Before wearing shoes...");
    hero.move();
    final NikeShoesHero nikeShoesHero = new NikeShoesHero(hero);
    System.out.println("After wearing shoes...");
    nikeShoesHero.move();
    nikeShoesHero.pose();
}

Output:

Before wearing shoes...
亚瑟走起来了。。。
After wearing shoes...
穿上布灵布灵的耐克鞋,亚瑟走起来了。。。
亚瑟摆了个Pose并说Just Do It!

总结

装饰器在Java的 I/O 实现中被广泛应用,可以看一下 InputStream 作为顶层的超类,FilterInputStream 可以理解为装饰类,BufferedInputStream 继承了FilterInputStream 作为具体的装饰类。

装饰者模式代理模式很像,都要有共同的接口,都是对原本的类的能力进行增强,但是还是有很大区别。代理模式是将被代理类隐藏起来,客户端无法知道被代理类是什么,如何做的增强。而装饰者模式客户端要提供被增强的对象,装饰类就像插件一样,一件一件套上,按需装备