装饰模式

/ 设计模式

装饰模式(Decorator)

动态的给某一对象添加额外的职责。也可以叫做包装器(Wrapper)。

GoF23种设计模式中,属于结构型模式( Structural patterns)

一般来说我们给一个类拓展新功能都会采用继承。但是继承的类都是静态的,也就说每支持一种新功能,就需要实现对应功能的继承类。当新功能之间有排列组合关系时,如果采用继承,那实现类就要爆炸了。

例如,我们想要做一个汉堡。该汉堡可以加热狗,芝士等配料。如果采用继承实现,我们就需要有汉堡,热狗汉堡,芝士汉堡,热狗芝士汉堡四个子类。如果再加上添加顺序,那么先加芝士或先加热狗就又不同了。因此,这么实现就会有上面所说的类爆炸情况了。

装饰模式就可以解决这个问题。装饰模式可以将汉堡与配料动态组合在一起。想要怎么搭配全交给顾客,顾客说怎么来就怎么搞。

实现

uml类图

decorator

角色说明

code

我们就以做汉堡举例。

对应角色

AbstractHamburg.java

public abstract class AbstractHamburg {

    abstract void process();
}

SpicyHamburg.java

public class SpicyHamburg extends AbstractHamburg {

    @Override
    void process() {
        System.out.println("做一个香辣汉堡");
    }
}

AbstractFixing.java

public abstract class AbstractFixing extends AbstractHamburg{

    private AbstractHamburg abstractHamburg;

    public AbstractFixing(AbstractHamburg abstractHamburg) {
        this.abstractHamburg = abstractHamburg;
    }

    @Override
    void process() {
        abstractHamburg.process();
    }
}

Cheese.java

public class Cheese extends AbstractFixing {
    public Cheese(AbstractHamburg abstractHamburg) {
        super(abstractHamburg);
    }

    @Override
    void process() {
        super.process();
        System.out.println("加一份芝士");
    }
}

HotDog.java

public class HotDog extends AbstractFixing {
    public HotDog(AbstractHamburg abstractHamburg) {
        super(abstractHamburg);
    }

    @Override
    void process() {
        super.process();
        System.out.println("加一份热狗");
    }
}

Test.java

public class Test {

    public static void main(String[] args) {
        // 加了芝士热狗的汉堡 = 芝士(热狗(辛辣汉堡)) 
        AbstractHamburg hamburg = new Cheese(new HotDog(new SpicyHamburg()));
        hamburg.process();
    }
}

output

做一个香辣汉堡
加一份热狗
加一份芝士

这种模式下,不管你是先要加热狗或者芝士,不管你要加几次,都可以任你组合,十分方便。

实例

总结

如果你需要一个可以动态拓展,自由组合的设计,装饰模式一定不要错过。