设计模式-06【装饰器模式--Decorator】

装饰器模式允许在不修改原有对象的基础上,通过装饰类添加新的功能。适用于避免大量子类扩展导致的类膨胀问题。本文通过咖啡店菜单的例子,展示了如何使用装饰器模式来扩展 Drink 类,如 Coffee、LongBlack、Decaf、Milk 和 Soy,以实现不同口味和价格的组合。
摘要由CSDN通过智能技术生成

装饰器模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法完整性的前提下,提供了额外的功能。

何时使用::一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。在不想增加很多子类的情况下扩展类。

如何解决:将具体功能职责划分,同时继承装饰者模式。

关键代码: 使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰器模式的目标。

优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

缺点:多层装饰比较复杂。


代码案例

构建抽象角色:

/**
 * @className: Drink
 * @description:
 * @author: charon
 * @create: 2022-03-19 22:48
 */
public abstract class Drink {

    /**
     * 描述
     */
    public String desc;

    /**
     * 价格
     */
    private float price = 0.0f;

    /**
     * Gets the value of desc
     *
     * @return the value of desc
     */
    public String getDesc() {
        return desc;
    }

    /**
     * Sets the desc
     *
     * @param desc desc
     */
    public void setDesc(String desc) {
        this.desc = desc;
    }

    /**
     * Gets the value of price
     *
     * @return the value of price
     */
    public float getPrice() {
        return price;
    }

    /**
     * Sets the price
     *
     * @param price price
     */
    public void setPrice(float price) {
        this.price = price;
    }

    /**
     * 计算费用的方法,交给子类实现
     * @return
     */
    public abstract float cost();
}

构建具体角色:

package com.charon.decorator;

/**
 * @className: Coffee
 * @description:
 * @author: charon
 * @create: 2022-03-19 22:37
 */
public class Coffee extends Drink{

    @Override
    public float cost() {
        return super.getPrice();
    }
}

package com.charon.decorator;

/**
 * @className: LongBlack
 * @description:
 * @author: charon
 * @create: 2022-03-19 23:16
 */
public class LongBlack extends Coffee{
    public LongBlack() {
        setDesc(" 美式咖啡 ");
        setPrice(5.0f);
    }
}

package com.charon.decorator;

/**
 * @className: Decaf
 * @description:
 * @author: charon
 * @create: 2022-03-19 23:11
 */
public class Decaf extends Coffee{
    public Decaf() {
        setDesc(" 无因咖啡  ");
        setPrice(1.0f);
    }
}


抽象装饰角色:

package com.charon.decorator;

/**
 * @className: Decorator
 * @description:
 * @author: charon
 * @create: 2022-03-19 23:13
 */
public class Decorator extends Drink{

    /**
     * 使用聚合的方式
     */
    private Drink drink;

    public Decorator(Drink drink) {
        this.drink = drink;
    }

    @Override
    public float cost() {
        return super.getPrice() + drink.cost();
    }

    @Override
    public String getDesc() {
        return super.getDesc() + "&&" + drink.getDesc();
    }
}

具体装饰角色:

package com.charon.decorator;

/**
 * @className: Milk
 * @description:
 * @author: charon
 * @create: 2022-03-19 23:17
 */
public class Milk extends Decorator{
    public Milk(Drink drink) {
        super(drink);
        setDesc(" 牛奶 ");
        setPrice(2.0f);
    }
}

package com.charon.decorator;

/**
 * @className: Soy
 * @description:
 * @author: charon
 * @create: 2022-03-19 23:18
 */
public class Soy extends Decorator{
    public Soy(Drink drink) {
        super(drink);
        setDesc(" 豆浆 ");
        setPrice(1.5f);
    }
}

测试

package com.charon.decorator;

/**
 * @className: Client
 * @description:
 * @author: charon
 * @create: 2022-03-19 23:19
 */
public class Client {
    public static void main(String[] args) {
        // 点一份美式咖啡
        Drink longBlack = new LongBlack();
        System.out.println(longBlack.getDesc() + " 费用: " + longBlack.cost());

        // 添加一点牛奶
        longBlack = new Milk(longBlack);
        System.out.println(" 添加了:" + longBlack.getDesc() + " 费用:" + longBlack.cost());

        // 再添加一点豆浆
        longBlack = new Soy(longBlack);
        System.out.println(" 添加了:" + longBlack.getDesc() + " 费用:" + longBlack.cost());
    }
}

运行结果

美式咖啡  费用: 5.0
添加了: 牛奶 && 美式咖啡  费用:7.0
添加了: 豆浆 && 牛奶 && 美式咖啡  费用:8.5

转载自:设计模式之装饰器模式 - pluto_charon - 博客园

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值