介绍Java装饰模式

介绍Java装饰模式

装饰模式用于给对象动态或静态地附加额外的责任。装饰器给原对象提供了额外功能接口。
实现该模式,我们更倾向于使用组合而不是继承,因为可以减少每个装饰元素子类化的开销。递归调用该模式可以根据需要对原对象进行多次装饰。

示例说明

假设我们有一个圣诞树对象需要装饰,装饰不能改变原对象,仅给对象增加额外功能。我们打算增加一些如花环(garland)、金属丝(tinsel)、树顶(treetop)、泡泡灯(bubble light)等:

介绍Java装饰模式该实现过程我们遵循GOF设计和命名规范,首先创建ChristmasTree 接口和其实现:

public interface ChristmasTree {
    String decorate();
}

接口实现如下:

public class ChristmasTreeImpl implements ChristmasTree {
 
    @Override
    public String decorate() {
        return "Christmas tree";
    }
}

现在给原对象创建抽象类TreeDecorator ,也实现ChristmasTree接口并包含原对象。其实现方法简单调用decorate()方法:

public abstract class TreeDecorator implements ChristmasTree {
    private ChristmasTree tree;
    
    public TreeDecorator(ChristmasTree tree) {
        this.tree = tree;
    }

    @Override
    public String decorate() {
        return tree.decorate();
    }
}

我们现在创建装饰元素。它们都继承抽象TreeDecorator类并根据需求修改decorate()方法:

public class BubbleLights extends TreeDecorator {
    public BubbleLights(ChristmasTree tree) {
        super(tree);
    }
     
    public String decorate() {
        return super.decorate() + decorateWithBubbleLights();
    }
     
    private String decorateWithBubbleLights() {
        return " with Bubble Lights";
    }
}

其他的装饰元素一样:

public class Garland extends TreeDecorator {
    public Garland(ChristmasTree tree) {
        super(tree);
    }
    
    public String decorate() {
        return super.decorate() + decorateWithGarland();
    }

    private String decorateWithGarland() {
        return " with Garland";
    }
}

下面测试结果为True:

@Test
public void whenDecoratorsInjectedAtRuntime_thenConfigSuccess() {
    ChristmasTree tree1 = new Garland(new ChristmasTreeImpl());
    assertEquals(tree1.decorate(), 
      "Christmas tree with Garland");
      
    ChristmasTree tree2 = new BubbleLights(
      new Garland(new Garland(new ChristmasTreeImpl())));
    assertEquals(tree2.decorate(), 
      "Christmas tree with Garland with Garland with Bubble Lights");
}

对第一个tree1对象,我们仅适用Garland进行装饰。而第二个tree2对象装饰一个BubbleLights 和两个Garlands。该模式让我们可以灵活地在运行时根据需要增加装饰元素。

总结

本文,我们探讨了装饰模式。一般用于下列场景:

  • 一般用于增加、增强,甚至删除对象行为或状态。
  • 只想修改类的单个对象的功能而不改变其他对象。