装饰器模式

144 阅读2分钟

这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战

装饰器模式

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

结构

  1. 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
  2. 具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
  3. 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
  4. 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

image.png

演示

1、定义抽象构件(Component)角色

定义衣服制作接口
public interface Clothes {
    void make();
}

2、定义体构件(ConcreteComponent)角色

刚开始需求只是制作上衣
public class JacketClothes implements Clothes {
    @Override
    public void make() {
        System.out.println("制作上衣");
    }
}

3、定义抽象装饰(Decorator)角色

上衣太单调,产品提出新需求想染个色,定义抽象装饰类,实现原功能接口
public abstract class ClothesDecorator implements Clothes {
    protected Clothes decoratorClothes;
    public ClothesDecorator(Clothes clothes) {
        this.decoratorClothes = clothes;
    }
    public void make() {
        this.decoratorClothes.make();
    }
}

4、定义具体装饰(ConcreteDecorator)角色

定义具体的装饰功能类,继承抽象装饰类,实现原功能接口,再原功能接口上再进行装饰
public class RedJacket extends ClothesDecorator {
    public RedJacket(Clothes clothes) {
        super(clothes);
    }
    @Override
    public void make() {
        super.make();
        setRedJacket();
    }
    public void setRedJacket() {
        System.out.println("上衣染红色!");
    }
}

5、客户端

public class Client {
    public static void main(String[] args) {
        Clothes clothes = new JacketClothes();
        ClothesDecorator redJacket = new RedJacket(clothes);
        System.out.println("原功能:");
        clothes.make(); // 制作上衣
        System.out.println("装饰后:");
        redJacket.make(); // 制作上衣 上衣染红色!
    }
}

总结

优点

  • 装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
  • 通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
  • 装饰器模式完全遵守开闭原则

缺点

装饰器模式会增加许多子类,过度使用会增加程序得复杂性。