案例外卖系统案例(一)、核心需求拆解本次开发的核心目标是在原有 “外卖菜品上架、浏览” 功能的基础上新增 “通过菜品唯一 ID 精准查询菜品信息” 的功能同时保证系统逻辑完整、用户交互友好。拆解为 3 个具体子需求数据层为菜品实体新增 “唯一 ID” 属性作为查询标识业务层实现 “根据输入 ID 遍历菜品列表、匹配并返回结果” 的逻辑交互层新增查询入口完善用户输入、结果反馈找到 / 未找到的交互流程。(二)、分阶段解题思路阶段 1数据模型改造Food 类核心思路扩展实体属性保证数据唯一性新增核心字段在原有name/originalPrice等属性基础上新增private int id字段作为菜品的唯一标识类似外卖平台的菜品编号完善构造方法保留无参构造满足基础对象创建需求扩展带参构造加入id参数支持创建时直接赋值补充访问方法为id字段生成getId()/setId()方法保证属性封装性符合面向对象 “封装” 原则优化展示逻辑重写toString()方法将id融入菜品信息展示方便用户查看 ID。关键考量ID 必须唯一因此不在用户输入环节手动填写而是由系统自动分配避免重复。阶段 2业务逻辑扩展FoodManager 类子步骤 1设计 ID 自动生成机制新增自增变量在FoodManager中定义private int nextId 1初始值为 1每次上架菜品后自增关联上架功能修改addFood()方法创建Food对象时将nextId作为 ID 传入随后nextId保证每个新菜品的 ID 唯一且连续如第 1 个菜品 ID1第 2 个 2以此类推。子步骤 2实现 “ID 查询” 核心逻辑入口设计在主菜单中新增 “3. 根据 ID 查询菜品” 选项关联queryFoodById()方法前置校验查询前先判断菜品列表是否为空若为空直接提示 “暂无菜品”避免无效遍历用户输入处理接收用户输入的目标 IDint targetId并处理输入后的换行符避免后续输入异常遍历匹配逻辑定义Food targetFood null作为 “匹配结果容器”增强 for 循环遍历foodList逐个对比菜品id与用户输入的targetId找到匹配项时将菜品对象赋值给targetFood并终止循环提升效率结果反馈若targetFood ! null打印匹配到的菜品详细信息若targetFood null提示 “未找到对应 ID 的菜品”保证用户体验。子步骤 3交互流程完善菜单扩展在showMenu()的 switch-case 中新增case 3调用查询方法异常防护对用户输入的非数字 ID如字母、符号虽基础版本未做校验但预留了扩展空间进阶可加输入合法性判断。阶段 3程序入口保持稳定FoodTest 类核心思路开闭原则对扩展开放、对修改关闭无需修改FoodTest类的任何代码仅需创建FoodManager对象并调用showMenu()原有 “上架、浏览” 功能不受影响新增功能通过扩展实现保证系统稳定性。(三)、关键设计原则与考量1. 面向对象核心原则封装性菜品的id属性私有化仅通过 Getter/Setter 访问避免外部直接修改开闭原则新增查询功能时仅扩展代码新增方法 / 字段不修改原有 “上架、浏览” 的核心逻辑单一职责Food类仅负责封装菜品数据FoodManager仅负责业务逻辑FoodTest仅负责启动程序职责清晰。2. 业务逻辑合理性ID 唯一性保障系统自动分配 ID而非用户输入从源头避免 ID 重复遍历效率找到匹配 ID 后立即break终止循环无需遍历全部列表提升查询效率用户体验查询前校验列表是否为空避免无效操作明确的结果反馈找到 / 未找到而非无提示或报错。3. 扩展性预留查询方法独立封装为queryFoodById()后续可基于此扩展 “ID 修改、ID 删除” 等功能自增 ID 机制可灵活调整如从 1000 开始编号适配实际业务场景。(四)、核心思路总结数据先行先扩展实体属性新增 ID为查询功能提供数据基础逻辑闭环查询功能包含 “输入→校验→遍历匹配→结果反馈” 完整流程无逻辑断点兼容扩展在不破坏原有功能的前提下扩展新功能符合软件开发的核心原则同时预留后续扩展空间如 ID 删除、修改。二、完整代码示例(一)、菜品类Food.java封装菜品的核心信息新增id字段用于唯一标识。public class Food { // 菜品唯一ID private int id; // 菜品名称 private String name; // 菜品原价 private double originalPrice; // 菜品优惠价 private double discountPrice; // 菜品其他信息如口味、规格等 private String info; // 无参构造 public Food() {} // 带参构造包含id public Food(int id, String name, double originalPrice, double discountPrice, String info) { this.id id; this.name name; this.originalPrice originalPrice; this.discountPrice discountPrice; this.info info; } // Getter和Setter方法 public int getId() { return id; } public void setId(int id) { this.id id; } public String getName() { return name; } public void setName(String name) { this.name name; } public double getOriginalPrice() { return originalPrice; } public void setOriginalPrice(double originalPrice) { this.originalPrice originalPrice; } public double getDiscountPrice() { return discountPrice; } public void setDiscountPrice(double discountPrice) { this.discountPrice discountPrice; } public String getInfo() { return info; } public void setInfo(String info) { this.info info; } // 重写toString方法方便打印菜品信息 Override public String toString() { return 【ID: id 】 name \n 信息 info \n 原价¥ originalPrice 优惠价¥ discountPrice \n ------------------------; } }(二)、菜品管理类FoodManager.java在原有功能基础上新增根据 ID 查询菜品的功能。import java.util.ArrayList; import java.util.Scanner; public class FoodManager { // 存储所有上架的菜品 private ArrayListFood foodList new ArrayList(); // 扫描器用于接收用户输入 private Scanner sc new Scanner(System.in); // 用于生成菜品ID自增 private int nextId 1; // 展示操作界面 public void showMenu() { while (true) { System.out.println(\n 外卖商家系统 ); System.out.println(1. 上架菜品); System.out.println(2. 浏览所有菜品); System.out.println(3. 根据ID查询菜品); System.out.println(4. 退出系统); System.out.print(请输入您的选择); int choice sc.nextInt(); sc.nextLine(); // 处理换行符 switch (choice) { case 1: addFood(); break; case 2: showAllFoods(); break; case 3: queryFoodById(); break; case 4: System.out.println(退出系统感谢使用); return; default: System.out.println(输入有误请重新选择); } } } // 上架菜品功能自动分配ID private void addFood() { System.out.println(\n 上架新菜品 ); System.out.print(请输入菜品名称); String name sc.nextLine(); System.out.print(请输入菜品原价); double originalPrice sc.nextDouble(); System.out.print(请输入菜品优惠价); double discountPrice sc.nextDouble(); sc.nextLine(); // 处理换行符 System.out.print(请输入菜品其他信息如口味、规格); String info sc.nextLine(); // 创建菜品对象自动生成ID并加入集合 Food food new Food(nextId, name, originalPrice, discountPrice, info); foodList.add(food); System.out.println(✅ 菜品【 name 】上架成功菜品ID food.getId()); } // 浏览所有菜品功能 private void showAllFoods() { System.out.println(\n 所有上架菜品 ); if (foodList.isEmpty()) { System.out.println(⚠️ 暂无上架菜品请先上架菜品); return; } // 遍历集合打印所有菜品信息 for (Food food : foodList) { System.out.println(food); } } // 根据ID查询菜品功能新增 private void queryFoodById() { System.out.println(\n 根据ID查询菜品 ); if (foodList.isEmpty()) { System.out.println(⚠️ 暂无上架菜品请先上架菜品); return; } System.out.print(请输入要查询的菜品ID); int targetId sc.nextInt(); sc.nextLine(); // 处理换行符 // 遍历集合查找匹配ID的菜品 Food targetFood null; for (Food food : foodList) { if (food.getId() targetId) { targetFood food; break; } } // 输出查询结果 if (targetFood ! null) { System.out.println(✅ 查询到菜品信息); System.out.println(targetFood); } else { System.out.println(❌ 未找到ID为【 targetId 】的菜品); } } }(三)、测试类FoodTest.java程序入口启动商家管理系统。public class FoodTest { public static void main(String[] args) { // 创建管理类对象并启动界面 FoodManager manager new FoodManager(); manager.showMenu(); } }三、核心知识点总结(一)、面向对象编程核心1. 封装特性强化属性封装为菜品新增id私有字段通过getId()/setId()方法控制访问避免外部直接修改保证数据安全性方法封装将 “ID 查询” 逻辑独立封装为queryFoodById()方法与 “上架”“浏览” 方法分离符合 “单一职责原则”便于维护和复用。2. 类的扩展与开闭原则扩展不修改新增 ID 查询功能时仅在原有Food类新增字段 / 方法、FoodManager类新增查询方法未改动 “上架”“浏览” 核心逻辑遵循 “对扩展开放、对修改关闭” 的开闭原则构造方法设计保留无参构造、扩展带参构造兼顾不同场景下的对象创建需求空对象初始化 / 全属性初始化。(二)、ArrayList 集合核心应用1. 集合遍历与匹配增强 for 循环遍历通过for (Food food : foodList)遍历菜品列表逐个对比food.getId()与目标 ID实现精准匹配匹配结果处理定义targetFood变量接收匹配结果遍历中找到目标后立即break终止循环提升查询效率。2. 集合数据管理动态存储利用ArrayList的动态扩容特性存储数量不固定的菜品对象无需担心长度限制数据校验查询前通过foodList.isEmpty()判断集合是否为空避免空列表遍历导致的无效操作。(三)、业务逻辑设计1. 唯一标识ID设计自增 ID 机制通过nextId自增变量为菜品自动分配唯一 ID避免用户手动输入导致的重复问题符合实际业务中 “菜品编号唯一” 的需求ID 关联展示重写toString()方法将 ID 融入菜品信息展示为查询功能提供可视化标识。2. 交互逻辑设计用户输入处理使用Scanner接收用户输入的 ID处理换行符避免输入异常结果反馈查询结果分为 “找到菜品展示详情” 和 “未找到菜品提示信息” 两种情况保证交互的友好性和完整性。(四)、Java 基础语法1. 流程控制分支结构在主菜单中通过switch-case新增查询功能入口扩展程序功能循环结构增强 for 循环实现列表遍历while(true)实现菜单循环展示。2. 变量与数据类型整型变量应用id和nextId使用int类型适配菜品编号的数值特性引用类型赋值通过Food targetFood null初始化引用变量接收匹配到的菜品对象利用 “引用指向对象” 的特性实现结果存储。(五)、核心知识点速记封装是面向对象的核心私有属性需通过 Getter/Setter 访问业务逻辑需封装为独立方法ArrayList 遍历匹配是查询功能的核心增强 for 循环简洁高效匹配后及时终止循环可提升性能唯一 ID 设计需保证唯一性系统自动分配自增是实际业务中最常用的实现方式交互逻辑需兼顾 “输入处理、前置校验、结果反馈”保证程序的实用性和友好性。
基于 ArrayList 与面向对象的外卖商家菜品管理系统实现
案例外卖系统案例(一)、核心需求拆解本次开发的核心目标是在原有 “外卖菜品上架、浏览” 功能的基础上新增 “通过菜品唯一 ID 精准查询菜品信息” 的功能同时保证系统逻辑完整、用户交互友好。拆解为 3 个具体子需求数据层为菜品实体新增 “唯一 ID” 属性作为查询标识业务层实现 “根据输入 ID 遍历菜品列表、匹配并返回结果” 的逻辑交互层新增查询入口完善用户输入、结果反馈找到 / 未找到的交互流程。(二)、分阶段解题思路阶段 1数据模型改造Food 类核心思路扩展实体属性保证数据唯一性新增核心字段在原有name/originalPrice等属性基础上新增private int id字段作为菜品的唯一标识类似外卖平台的菜品编号完善构造方法保留无参构造满足基础对象创建需求扩展带参构造加入id参数支持创建时直接赋值补充访问方法为id字段生成getId()/setId()方法保证属性封装性符合面向对象 “封装” 原则优化展示逻辑重写toString()方法将id融入菜品信息展示方便用户查看 ID。关键考量ID 必须唯一因此不在用户输入环节手动填写而是由系统自动分配避免重复。阶段 2业务逻辑扩展FoodManager 类子步骤 1设计 ID 自动生成机制新增自增变量在FoodManager中定义private int nextId 1初始值为 1每次上架菜品后自增关联上架功能修改addFood()方法创建Food对象时将nextId作为 ID 传入随后nextId保证每个新菜品的 ID 唯一且连续如第 1 个菜品 ID1第 2 个 2以此类推。子步骤 2实现 “ID 查询” 核心逻辑入口设计在主菜单中新增 “3. 根据 ID 查询菜品” 选项关联queryFoodById()方法前置校验查询前先判断菜品列表是否为空若为空直接提示 “暂无菜品”避免无效遍历用户输入处理接收用户输入的目标 IDint targetId并处理输入后的换行符避免后续输入异常遍历匹配逻辑定义Food targetFood null作为 “匹配结果容器”增强 for 循环遍历foodList逐个对比菜品id与用户输入的targetId找到匹配项时将菜品对象赋值给targetFood并终止循环提升效率结果反馈若targetFood ! null打印匹配到的菜品详细信息若targetFood null提示 “未找到对应 ID 的菜品”保证用户体验。子步骤 3交互流程完善菜单扩展在showMenu()的 switch-case 中新增case 3调用查询方法异常防护对用户输入的非数字 ID如字母、符号虽基础版本未做校验但预留了扩展空间进阶可加输入合法性判断。阶段 3程序入口保持稳定FoodTest 类核心思路开闭原则对扩展开放、对修改关闭无需修改FoodTest类的任何代码仅需创建FoodManager对象并调用showMenu()原有 “上架、浏览” 功能不受影响新增功能通过扩展实现保证系统稳定性。(三)、关键设计原则与考量1. 面向对象核心原则封装性菜品的id属性私有化仅通过 Getter/Setter 访问避免外部直接修改开闭原则新增查询功能时仅扩展代码新增方法 / 字段不修改原有 “上架、浏览” 的核心逻辑单一职责Food类仅负责封装菜品数据FoodManager仅负责业务逻辑FoodTest仅负责启动程序职责清晰。2. 业务逻辑合理性ID 唯一性保障系统自动分配 ID而非用户输入从源头避免 ID 重复遍历效率找到匹配 ID 后立即break终止循环无需遍历全部列表提升查询效率用户体验查询前校验列表是否为空避免无效操作明确的结果反馈找到 / 未找到而非无提示或报错。3. 扩展性预留查询方法独立封装为queryFoodById()后续可基于此扩展 “ID 修改、ID 删除” 等功能自增 ID 机制可灵活调整如从 1000 开始编号适配实际业务场景。(四)、核心思路总结数据先行先扩展实体属性新增 ID为查询功能提供数据基础逻辑闭环查询功能包含 “输入→校验→遍历匹配→结果反馈” 完整流程无逻辑断点兼容扩展在不破坏原有功能的前提下扩展新功能符合软件开发的核心原则同时预留后续扩展空间如 ID 删除、修改。二、完整代码示例(一)、菜品类Food.java封装菜品的核心信息新增id字段用于唯一标识。public class Food { // 菜品唯一ID private int id; // 菜品名称 private String name; // 菜品原价 private double originalPrice; // 菜品优惠价 private double discountPrice; // 菜品其他信息如口味、规格等 private String info; // 无参构造 public Food() {} // 带参构造包含id public Food(int id, String name, double originalPrice, double discountPrice, String info) { this.id id; this.name name; this.originalPrice originalPrice; this.discountPrice discountPrice; this.info info; } // Getter和Setter方法 public int getId() { return id; } public void setId(int id) { this.id id; } public String getName() { return name; } public void setName(String name) { this.name name; } public double getOriginalPrice() { return originalPrice; } public void setOriginalPrice(double originalPrice) { this.originalPrice originalPrice; } public double getDiscountPrice() { return discountPrice; } public void setDiscountPrice(double discountPrice) { this.discountPrice discountPrice; } public String getInfo() { return info; } public void setInfo(String info) { this.info info; } // 重写toString方法方便打印菜品信息 Override public String toString() { return 【ID: id 】 name \n 信息 info \n 原价¥ originalPrice 优惠价¥ discountPrice \n ------------------------; } }(二)、菜品管理类FoodManager.java在原有功能基础上新增根据 ID 查询菜品的功能。import java.util.ArrayList; import java.util.Scanner; public class FoodManager { // 存储所有上架的菜品 private ArrayListFood foodList new ArrayList(); // 扫描器用于接收用户输入 private Scanner sc new Scanner(System.in); // 用于生成菜品ID自增 private int nextId 1; // 展示操作界面 public void showMenu() { while (true) { System.out.println(\n 外卖商家系统 ); System.out.println(1. 上架菜品); System.out.println(2. 浏览所有菜品); System.out.println(3. 根据ID查询菜品); System.out.println(4. 退出系统); System.out.print(请输入您的选择); int choice sc.nextInt(); sc.nextLine(); // 处理换行符 switch (choice) { case 1: addFood(); break; case 2: showAllFoods(); break; case 3: queryFoodById(); break; case 4: System.out.println(退出系统感谢使用); return; default: System.out.println(输入有误请重新选择); } } } // 上架菜品功能自动分配ID private void addFood() { System.out.println(\n 上架新菜品 ); System.out.print(请输入菜品名称); String name sc.nextLine(); System.out.print(请输入菜品原价); double originalPrice sc.nextDouble(); System.out.print(请输入菜品优惠价); double discountPrice sc.nextDouble(); sc.nextLine(); // 处理换行符 System.out.print(请输入菜品其他信息如口味、规格); String info sc.nextLine(); // 创建菜品对象自动生成ID并加入集合 Food food new Food(nextId, name, originalPrice, discountPrice, info); foodList.add(food); System.out.println(✅ 菜品【 name 】上架成功菜品ID food.getId()); } // 浏览所有菜品功能 private void showAllFoods() { System.out.println(\n 所有上架菜品 ); if (foodList.isEmpty()) { System.out.println(⚠️ 暂无上架菜品请先上架菜品); return; } // 遍历集合打印所有菜品信息 for (Food food : foodList) { System.out.println(food); } } // 根据ID查询菜品功能新增 private void queryFoodById() { System.out.println(\n 根据ID查询菜品 ); if (foodList.isEmpty()) { System.out.println(⚠️ 暂无上架菜品请先上架菜品); return; } System.out.print(请输入要查询的菜品ID); int targetId sc.nextInt(); sc.nextLine(); // 处理换行符 // 遍历集合查找匹配ID的菜品 Food targetFood null; for (Food food : foodList) { if (food.getId() targetId) { targetFood food; break; } } // 输出查询结果 if (targetFood ! null) { System.out.println(✅ 查询到菜品信息); System.out.println(targetFood); } else { System.out.println(❌ 未找到ID为【 targetId 】的菜品); } } }(三)、测试类FoodTest.java程序入口启动商家管理系统。public class FoodTest { public static void main(String[] args) { // 创建管理类对象并启动界面 FoodManager manager new FoodManager(); manager.showMenu(); } }三、核心知识点总结(一)、面向对象编程核心1. 封装特性强化属性封装为菜品新增id私有字段通过getId()/setId()方法控制访问避免外部直接修改保证数据安全性方法封装将 “ID 查询” 逻辑独立封装为queryFoodById()方法与 “上架”“浏览” 方法分离符合 “单一职责原则”便于维护和复用。2. 类的扩展与开闭原则扩展不修改新增 ID 查询功能时仅在原有Food类新增字段 / 方法、FoodManager类新增查询方法未改动 “上架”“浏览” 核心逻辑遵循 “对扩展开放、对修改关闭” 的开闭原则构造方法设计保留无参构造、扩展带参构造兼顾不同场景下的对象创建需求空对象初始化 / 全属性初始化。(二)、ArrayList 集合核心应用1. 集合遍历与匹配增强 for 循环遍历通过for (Food food : foodList)遍历菜品列表逐个对比food.getId()与目标 ID实现精准匹配匹配结果处理定义targetFood变量接收匹配结果遍历中找到目标后立即break终止循环提升查询效率。2. 集合数据管理动态存储利用ArrayList的动态扩容特性存储数量不固定的菜品对象无需担心长度限制数据校验查询前通过foodList.isEmpty()判断集合是否为空避免空列表遍历导致的无效操作。(三)、业务逻辑设计1. 唯一标识ID设计自增 ID 机制通过nextId自增变量为菜品自动分配唯一 ID避免用户手动输入导致的重复问题符合实际业务中 “菜品编号唯一” 的需求ID 关联展示重写toString()方法将 ID 融入菜品信息展示为查询功能提供可视化标识。2. 交互逻辑设计用户输入处理使用Scanner接收用户输入的 ID处理换行符避免输入异常结果反馈查询结果分为 “找到菜品展示详情” 和 “未找到菜品提示信息” 两种情况保证交互的友好性和完整性。(四)、Java 基础语法1. 流程控制分支结构在主菜单中通过switch-case新增查询功能入口扩展程序功能循环结构增强 for 循环实现列表遍历while(true)实现菜单循环展示。2. 变量与数据类型整型变量应用id和nextId使用int类型适配菜品编号的数值特性引用类型赋值通过Food targetFood null初始化引用变量接收匹配到的菜品对象利用 “引用指向对象” 的特性实现结果存储。(五)、核心知识点速记封装是面向对象的核心私有属性需通过 Getter/Setter 访问业务逻辑需封装为独立方法ArrayList 遍历匹配是查询功能的核心增强 for 循环简洁高效匹配后及时终止循环可提升性能唯一 ID 设计需保证唯一性系统自动分配自增是实际业务中最常用的实现方式交互逻辑需兼顾 “输入处理、前置校验、结果反馈”保证程序的实用性和友好性。