创建一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能

  1. 抽象组件:需要装饰的抽象对象(接口或抽象父类)

  2. 具体组件:需要装饰的对象

  3. 抽象装饰类:包含了对抽象组件的引用以及装饰者共有的方法

  4. 具体装饰类:被装饰的对象

//抽象组件
interface Drink {
    double cost();
    String info();
}
 
//具体组件
class Coffe implements Drink {
    @Override
    public double cost() {
        return 8;
    }
 
    @Override
    public String info() {
        return "原味咖啡";
    }
}
 
//抽象装饰类
abstract class Decorate implements Drink {
    //对抽象组件的引用
    private Drink drink;
 
    public Decorate(Drink drink) {
        this.drink = drink;
    }
 
    @Override
    public double cost() {
        return this.drink.cost();
    }
 
    @Override
    public String info() {
        return this.drink.info();
    }
}
 
//具体装饰类
class Suger extends Decorate {
    public Suger(Drink drink) {
        //调用父类构造方法
        super(drink);
    }
 
    @Override
    public double cost() {
        return super.cost()+2;
    }
 
    @Override
    public String info() {
        return super.info()+"加了糖";
    }
}
 
class Milk extends Decorate {
    public Milk(Drink drink) {
        super(drink);
    }
 
    @Override
    public double cost() {
        return super.cost()+4;
    }
 
    @Override
    public String info() {
        return super.info()+"加了牛奶";
    }
}
//test
public class Main {
    public static void main(String[] args) {
        /**
         * 原味咖啡-->8.0
         * 原味咖啡加了糖-->10.0
         * 原味咖啡加了牛奶-->12.0
         * 原味咖啡加了糖加了牛奶-->14.0
         */
        Drink coffe = new Coffe();
        System.out.println(coffe.info()+"-->"+coffe.cost());
        Decorate suger = new Suger(coffe);
        System.out.println(suger.info()+"-->"+suger.cost());
        Decorate milk = new Milk(coffe);
        System.out.println(milk.info()+"-->"+milk.cost());
        milk = new Milk(suger);
        System.out.println(milk.info()+"-->"+milk.cost());
    }
}