Skip to main content
 首页 » 编程设计

Java装饰模式

2022年07月19日137thcjp

介绍Java装饰模式

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

示例说明

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

https://www.baeldung.com/wp-content/uploads/2017/09/8poz64T.jpg该实现过程我们遵循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。该模式让我们可以灵活地在运行时根据需要增加装饰元素。

总结

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

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

本文参考链接:https://blog.csdn.net/neweastsun/article/details/89736481
阅读延展