Java设计模式实战:装饰模式在星巴克咖啡系统中的应用

一、装饰模式简介

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

二、星巴克咖啡系统设计

根据提供的UML类图,我们来设计一个星巴克咖啡下单系统,该系统可以计算不同咖啡和调料组合的价格。

系统组成

  1. 抽象组件(Beverage):相当于Component类,是所有咖啡和调料的基类

  2. 具体组件:HouseBlend、Expresso、DarkRoast、Decaf,代表不同类型的咖啡

  3. 装饰器(CondimentDecorator):抽象装饰类

  4. 具体装饰器:Milk、Mocha、Soy、Whip,代表不同的调料

三、代码实现

1. 抽象组件(Beverage)

复制代码
/**
 * 抽象组件 - 饮料基类
 * 相当于装饰模式中的Component角色
 */
public abstract class Beverage {
    // 饮料描述,初始为"Unknown Beverage"
    String description = "Unknown Beverage";
    
    /**
     * 获取饮料描述
     * @return 饮料描述字符串
     */
    public String getDescription() {
        return description;
    }
    
    /**
     * 计算饮料价格 - 抽象方法,由子类实现
     * @return 饮料价格
     */
    public abstract double cost();
}

2. 具体组件(各种咖啡类型)

2.1 HouseBlend 咖啡

复制代码
/**
 * 具体组件 - 混合咖啡
 */
public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = "House Blend Coffee";
    }
    
    @Override
    public double cost() {
        return 0.89;  // 基础价格0.89美元
    }
}

2.2 Expresso 咖啡

复制代码
/**
 * 具体组件 - 浓缩咖啡
 */
public class Expresso extends Beverage {
    public Expresso() {
        description = "Expresso";
    }
    
    @Override
    public double cost() {
        return 1.99;  // 基础价格1.99美元
    }
}

2.3 DarkRoast 咖啡

复制代码
/**
 * 具体组件 - 深焙咖啡
 */
public class DarkRoast extends Beverage {
    public DarkRoast() {
        description = "Dark Roast Coffee";
    }
    
    @Override
    public double cost() {
        return 0.99;  // 基础价格0.99美元
    }
}

2.4 Decaf 咖啡

复制代码
/**
 * 具体组件 - 低因咖啡
 */
public class Decaf extends Beverage {
    public Decaf() {
        description = "Decaf Coffee";
    }
    
    @Override
    public double cost() {
        return 1.05;  // 基础价格1.05美元
    }
}

3. 抽象装饰器(CondimentDecorator)

复制代码
/**
 * 抽象装饰器 - 调料装饰器基类
 * 继承自Beverage,所以装饰器可以嵌套装饰器
 */
public abstract class CondimentDecorator extends Beverage {
    /**
     * 获取完整描述 - 抽象方法
     * 每个具体装饰器需要实现如何添加自己的描述
     */
    @Override
    public abstract String getDescription();
}

4. 具体装饰器(各种调料)

4.1 Milk 牛奶

复制代码
/**
 * 具体装饰器 - 牛奶
 */
public class Milk extends CondimentDecorator {
    // 被装饰的饮料
    Beverage beverage;
    
    public Milk(Beverage beverage) {
        this.beverage = beverage;
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Milk";  // 添加牛奶描述
    }
    
    @Override
    public double cost() {
        return beverage.cost() + 0.10;  // 增加0.10美元
    }
}

4.2 Mocha 摩卡

复制代码
/**
 * 具体装饰器 - 摩卡
 */
public class Mocha extends CondimentDecorator {
    Beverage beverage;
    
    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Mocha";  // 添加摩卡描述
    }
    
    @Override
    public double cost() {
        return beverage.cost() + 0.20;  // 增加0.20美元
    }
}

4.3 Soy 豆浆

复制代码
/**
 * 具体装饰器 - 豆浆
 */
public class Soy extends CondimentDecorator {
    Beverage beverage;
    
    public Soy(Beverage beverage) {
        this.beverage = beverage;
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Soy";  // 添加豆浆描述
    }
    
    @Override
    public double cost() {
        return beverage.cost() + 0.15;  // 增加0.15美元
    }
}

4.4 Whip 奶泡

复制代码
/**
 * 具体装饰器 - 奶泡
 */
public class Whip extends CondimentDecorator {
    Beverage beverage;
    
    public Whip(Beverage beverage) {
        this.beverage = beverage;
    }
    
    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Whip";  // 添加奶泡描述
    }
    
    @Override
    public double cost() {
        return beverage.cost() + 0.10;  // 增加0.10美元
    }
}

5. 客户端使用示例

复制代码
/**
 * 星巴克咖啡店 - 客户端代码
 */
public class StarbuzzCoffee {
    public static void main(String args[]) {
        // 示例1:一杯纯Espresso
        Beverage beverage1 = new Expresso();
        System.out.println(beverage1.getDescription() + " $" + beverage1.cost());
        
        // 示例2:DarkRoast加双份Mocha和Whip
        Beverage beverage2 = new DarkRoast();
        beverage2 = new Mocha(beverage2);  // 第一次装饰:加Mocha
        beverage2 = new Mocha(beverage2);  // 第二次装饰:再加Mocha
        beverage2 = new Whip(beverage2);   // 第三次装饰:加Whip
        System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
        
        // 示例3:HouseBlend加Soy、Mocha和Whip
        Beverage beverage3 = new HouseBlend();
        beverage3 = new Soy(beverage3);   // 第一次装饰:加Soy
        beverage3 = new Mocha(beverage3);  // 第二次装饰:加Mocha
        beverage3 = new Whip(beverage3);   // 第三次装饰:加Whip
        System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
    }
}

四、代码结构说明

  1. Beverage 是所有饮料的基类,定义了基本接口

  2. 具体咖啡类型(HouseBlend、Expresso等)继承Beverage,实现具体价格

  3. CondimentDecorator是装饰器基类,也继承自Beverage

  4. 具体调料(Milk、Mocha等)继承CondimentDecorator,包装一个Beverage对象

  5. 客户端可以自由组合咖啡和调料,通过层层装饰实现复杂组合

五、装饰模式的优势

  1. 灵活性:可以动态地添加或删除功能,比继承更灵活

  2. 避免类爆炸:不需要为每种组合创建子类

  3. 符合开闭原则:对扩展开放,对修改关闭

  4. 运行时添加功能:可以在运行时决定添加哪些装饰

六、总结

通过这个星巴克咖啡系统的例子,我们看到了装饰模式在实际应用中的强大之处。它让我们能够轻松地组合各种咖啡和调料,而不需要创建大量的子类。这种模式特别适合那些需要动态、透明地添加对象功能的场景。

相关推荐
noravinsc22 分钟前
python提升图片清晰度
开发语言·python
一一Null28 分钟前
Android studio 动态布局
android·java·android studio
假女吖☌30 分钟前
Maven 编译指定模版
java·开发语言·maven
体育分享_大眼2 小时前
从零搭建高并发体育直播网站:架构设计、核心技术与性能优化实战
java·性能优化·系统架构
水w3 小时前
【Python爬虫】简单案例介绍1
开发语言·爬虫·python
琢磨先生David3 小时前
Java 在人工智能领域的突围:从企业级架构到边缘计算的技术革新
java·人工智能·架构
计算机学姐4 小时前
基于SpringBoo的地方美食分享网站
java·vue.js·mysql·tomcat·mybatis·springboot·美食
qq_365911605 小时前
GPT-4、Grok 3与Gemini 2.0 Pro:三大AI模型的语气、风格与能力深度对比
开发语言
Hanson Huang7 小时前
【数据结构】堆排序详细图解
java·数据结构·排序算法·堆排序
Susea&7 小时前
数据结构初阶:队列
c语言·开发语言·数据结构