9.装饰器模式

装饰器模式


装饰器模式(Decorator Pattern) 允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

装饰器模式的结构: 原有功能类和装饰器类都必须实现同一个接口,并且装饰器类还需要聚合原有功能类。

主要解决: 一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

案例:

咖啡店卖咖啡,咖啡有美式咖啡、无因咖啡等。
咖啡的配料有:巧克力、牛奶等。
点一份咖啡+n种配料,那么要算出最终价钱,例如点美式咖啡+2份巧克力+1份牛奶,也就是点击的量和种类是随机的。

在这里插入图片描述
上图解释:

drink:这个类就是公共接口类,原有功能类和装饰器类都需要去实现它;
图左半部分为原有功能类;
Decorator:装饰器类,必须实现公共接口类(Drink)和聚合该公共接口类(Drink,聚合的这个类就是被装饰者);
图右半部分为实现的装饰器类;

在这里插入图片描述
上图解释:

LongBlack为最开始的被装饰者类,将LongBlack传入Milk类(装饰者类)后,形成一个新的被装饰者类,以此类推。

在装饰者模式中,多次装饰后,方法的调用其实就是递归调用;

/**
 * 定义一个公共的抽象类,这个类会被装饰者和被装饰者继承,也就是说装饰者和被装饰者需要有共同的方法
 */
public abstract class Common {
    public String des;
    private float price = 0f;
    public abstract float cast();

    public String getDes() {
        return des;
    }

    public void setDes(String des) {
        this.des = des;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }
}
//以下是被装饰者
/**
 * 定义一个咖啡的缓冲层,可以把咖啡的公共方法写在这里面
 */
public class Coffe extends Common {
    public float cast() {
        //因为咖啡只点一次,这里的价格就是它自己的价格
        return super.getPrice();
    }
}

/**
 * 美式咖啡
 */
public class USACoffe extends Coffe {
    public USACoffe() {
        setDes("美式咖啡");
        setPrice(8f);
    }
}

//以下是装饰者

/**
 * 定义一个装饰者的父类,该类必须组合被装饰者
 */
public class Decorator extends Common {
    //common 这个是被装饰者
    private Common common;

    public Decorator(Common common) {
        this.common = common;
    }

    public float cast() {
        //super.getPrice()==配料自己的价格  common.getPrice()==这个是前面被装饰者的价格
        //super.getPrice() + common.cast()  这是一句递归代码,common.cast()这个代码最终会指向USACoffe里面定义的价格
        return super.getPrice() + common.cast();
    }

    @Override
    public String getDes() {
        //common.getDes()这个代码最终会指向USACoffe里面定义的描述
        return des +"  " +getPrice()+"&&"+common.getDes();
    }
}

/**
 * 定义一个牛奶配料,继承装饰者类
 */
public class Milk extends Decorator{
    public Milk(Common common) {
        super(common);
        setDes("牛奶");
        setPrice(1f);
    }
}

/**
 * 定义一个巧克力配料,继承装饰者类
 */
public class QiaoKeLi extends Decorator{
    public QiaoKeLi(Common common) {
        super(common);
        setDes("巧克力");
        setPrice(3f);
    }
}

public class Client {
    public static void main(String[] args) {
        Common common = new USACoffe();//点一个美式咖啡
        common = new QiaoKeLi (common);//点一个巧克力配料
        common = new Milk(common);//点一个牛奶配料
        System.out.println(common.cast());
        System.out.println(common.getDes());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT界的老菜鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值