
简介本资源是面向软件工程专业本科生及设计模式初学者的课程大作业实践项目聚焦服装管理系统的架构设计与模式落地帮助学习者深入理解设计模式在真实业务场景中的选型依据与实现细节。压缩包共39个文件含17个Java源码覆盖MVC分层、单例/工厂/策略等核心模式实现、14张PNG界面与类图直观展示系统交互逻辑与结构设计、4个XML配置文件支撑Spring或GUI布局、1份PPTX项目演示文稿含需求分析、架构对比与设计决策说明及1份DOC软件设计说明书含数据库ER图、模块功能表与测试用例整体2.4MB结构完整、开箱即学。已有5459人学习下载提供从UML建模、代码实现、文档撰写到汇报展示的全流程参考特别适合课程设计复现、毕业设计选题拓展及设计模式综合应用能力提升。1. 为什么一个“服装管理系统”大作业能逼出学生对设计模式和架构的全部认知盲区这不是一个简单的 CRUD 管理系统——它是一面镜子照出你是否真能把《软件设计模式与体系结构》课本里的抽象概念焊进真实业务逻辑里。某高校期末大作业要求用 Java或 C#实现一个支持多角色管理员、店员、顾客、多状态上架/下架/售罄/调拨、多维度分类品牌季节尺码风格的服装库存与销售协同系统。表面看是增删改查但一旦开始处理“同一款连衣裙在A店有S/M/L在B店只有M/XL且B店刚申请调拨2件到A店”这类场景单靠 if-else 或硬编码枚举就立刻崩盘。学生普遍卡在三个致命节点状态流转混乱比如“售罄”后还能被下单谁来校验、扩展成本爆炸新增“会员专属折扣”要改7个类、测试覆盖无力改一个价格策略整个结算模块全红。这恰恰是设计模式与体系结构课程最核心的交付目标让你在代码还没写完时就预判出哪里会“长肿瘤”。本文不讲 UML 图怎么画只带你用真实可运行的代码结构把工厂模式管创建、策略模式管折扣、状态模式管库存生命周期、观察者模式管库存变更通知——一条线串起来跑通从登录到生成销售单的最小闭环。适合正在赶工、想少走弯路或已提交初版但被导师批“架构感缺失”的同学。2. 用状态模式重构库存生命周期让“上架→售罄→下架”不再靠 if-else 硬扛服装库存的状态不是静态标签而是一套有严格流转规则的生命周期。硬编码判断if (status sold_out) { ... } else if (status discontinued) { ... }会导致两个问题一是新增状态如“临时冻结”要全局搜索修改所有条件分支二是状态合法性校验散落在各处容易出现“售罄商品还能被加购”的逻辑漏洞。状态模式的核心思想是把每个状态封装成独立类由上下文Context委托给当前状态对象处理行为并决定下一个状态。2.1 定义状态接口与具体状态类// 库存状态接口所有状态必须实现的行为契约 public interface InventoryState { // 处理“上架”操作仅部分状态允许 void handleList(InventoryContext context); // 处理“售出”操作仅部分状态允许 void handleSell(InventoryContext context); // 处理“下架”操作仅部分状态允许 void handleUnlist(InventoryContext context); // 获取状态名称用于日志和前端展示 String getStateName(); } // 上架状态可售可售出可下架 public class ListedState implements InventoryState { Override public void handleList(InventoryContext context) { // 已上架无需重复操作 System.out.println(警告商品已处于上架状态); } Override public void handleSell(InventoryContext context) { context.decreaseStock(1); // 扣减1件库存 if (context.getStock() 0) { context.setState(new SoldOutState()); // 自动转入售罄 } } Override public void handleUnlist(InventoryContext context) { context.setState(new UnlistedState()); // 主动下架 } Override public String getStateName() { return 上架; } } // 售罄状态不可售出可重新上架不可下架需先上架再下架 public class SoldOutState implements InventoryState { Override public void handleList(InventoryContext context) { context.setState(new ListedState()); // 补货后重新上架 } Override public void handleSell(InventoryContext context) { throw new IllegalStateException(错误售罄商品无法售出); } Override public void handleUnlist(InventoryContext context) { throw new IllegalStateException(错误售罄商品不能直接下架请先上架); } Override public String getStateName() { return 售罄; } } // 下架状态不可售出不可上架需管理员审核可重新上架 public class UnlistedState implements InventoryState { Override public void handleList(InventoryContext context) { // 下架商品重新上架需触发审核流程模拟 System.out.println(提示下架商品重新上架需管理员审核已提交申请); context.setState(new PendingReviewState()); } Override public void handleSell(InventoryContext context) { throw new IllegalStateException(错误下架商品无法售出); } Override public void handleUnlist(InventoryContext context) { // 已下架无需操作 System.out.println(警告商品已处于下架状态); } Override public String getStateName() { return 下架; } }逻辑说明InventoryState接口定义了所有状态必须响应的公共行为但每个实现类只负责自己状态下的合法操作。例如SoldOutState.handleSell()直接抛异常而非返回错误码——这强制调用方必须处理状态不合法的场景避免静默失败。handleSell()中库存扣减后自动切换状态体现了状态流转的内聚性。2.2 构建上下文类并集成状态机// 库存上下文持有当前状态引用和业务数据 public class InventoryContext { private InventoryState state; private String itemId; private int stock; // 当前库存数量 private String location; // 所属门店ID public InventoryContext(String itemId, int initialStock, String location) { this.itemId itemId; this.stock initialStock; this.location location; // 初始状态为上架新入库商品默认可售 this.state new ListedState(); } // 委托给当前状态处理行为 public void list() { state.handleList(this); } public void sell() { state.handleSell(this); } public void unlist() { state.handleUnlist(this); } // 状态变更入口仅状态类内部可调用 public void setState(InventoryState newState) { this.state newState; System.out.println(【状态变更】 itemId location → newState.getStateName()); } // 辅助方法扣减库存供状态类内部调用 public void decreaseStock(int quantity) { this.stock - quantity; System.out.println(【库存扣减】 itemId location - quantity 剩余 this.stock); } // Getter 方法供外部查询 public String getStateName() { return state.getStateName(); } public int getStock() { return stock; } public String getItemId() { return itemId; } }参数说明InventoryContext是状态模式的“舞台”它不关心状态如何变化只负责持有数据和转发请求。setState()方法设为public是为了状态类能主动切换但实际项目中可进一步封装为包级私有default访问修饰符防止外部误操作。decreaseStock()是典型的“上下文提供数据状态控制逻辑”的分工体现。2.3 在业务服务中调用状态机// 模拟一个库存服务类 public class InventoryService { // 持有所有库存项的上下文映射实际项目中应从数据库加载 private MapString, InventoryContext inventoryMap new HashMap(); public InventoryService() { // 初始化示例数据A店有3件连衣裙B店有5件 inventoryMap.put(DRESS-001STORE-A, new InventoryContext(DRESS-001, 3, STORE-A)); inventoryMap.put(DRESS-001STORE-B, new InventoryContext(DRESS-001, 5, STORE-B)); } // 处理用户下单请求简化版 public boolean processOrder(String itemId, String storeId) { String key itemId storeId; InventoryContext context inventoryMap.get(key); if (context null) { System.out.println(错误未找到商品 itemId 在门店 storeId); return false; } try { context.sell(); // 交由状态机处理 return true; } catch (IllegalStateException e) { System.out.println(订单失败 e.getMessage()); return false; } } // 查询商品当前状态 public String getInventoryStatus(String itemId, String storeId) { String key itemId storeId; InventoryContext context inventoryMap.get(key); return context ! null ? context.getStateName() : 未知; } } // 测试驱动验证状态流转 public class StatePatternDemo { public static void main(String[] args) { InventoryService service new InventoryService(); System.out.println( 初始状态 ); System.out.println(A店连衣裙状态 service.getInventoryStatus(DRESS-001, STORE-A)); // 上架 System.out.println(\n A店售出3件 ); service.processOrder(DRESS-001, STORE-A); // 剩2 service.processOrder(DRESS-001, STORE-A); // 剩1 service.processOrder(DRESS-001, STORE-A); // 剩0 → 自动变售罄 System.out.println(\n 尝试在售罄状态下再售出 ); service.processOrder(DRESS-001, STORE-A); // 抛异常 System.out.println(\n 售罄后补货上架 ); InventoryContext ctx service.getInventoryContext(DRESS-001STORE-A); if (ctx ! null) { ctx.list(); // 重新上架 } } }关键点processOrder()方法完全不关心状态细节只调用context.sell()。状态流转逻辑被彻底隔离在状态类内部。当需要新增“临时冻结”状态时只需新增FrozenState类并实现接口无需修改InventoryContext或任何服务类——这就是开闭原则的落地。测试用例清晰展示了状态自动切换售罄和非法操作拦截售罄后下单两个核心价值。3. 用策略模式解耦价格计算让“会员价/满减/节日折扣”自由组合不改一行结算代码服装销售的定价规则极其灵活新会员首单8折、VIP客户全场9折、满300减50、双十二跨店满减……如果把这些逻辑全塞进OrderService.calculateTotal()里每次营销活动上线都要改核心结算方法风险高、测试难、上线慢。策略模式的解法是把每种定价规则封装成独立策略类结算服务通过配置动态选择策略实现“算法可插拔”。3.1 定义价格计算策略接口与标准实现// 价格计算策略接口输入订单信息输出最终价格 public interface PricingStrategy { BigDecimal calculatePrice(Order order, ListOrderItem items); String getStrategyName(); // 用于日志和审计 } // 基础价格策略按商品标价累加无任何折扣 public class BasePriceStrategy implements PricingStrategy { Override public BigDecimal calculatePrice(Order order, ListOrderItem items) { BigDecimal total BigDecimal.ZERO; for (OrderItem item : items) { total total.add(item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity()))); } return total; } Override public String getStrategyName() { return 基础价格; } } // 会员折扣策略根据会员等级打不同折扣 public class MemberDiscountStrategy implements PricingStrategy { private final MapString, BigDecimal discountMap; // 会员等级 - 折扣率如0.9表示9折 public MemberDiscountStrategy() { this.discountMap new HashMap(); discountMap.put(GOLD, new BigDecimal(0.85)); // 黄金会员85折 discountMap.put(SILVER, new BigDecimal(0.90)); // 白银会员9折 discountMap.put(BRONZE, new BigDecimal(0.95)); // 青铜会员95折 } Override public BigDecimal calculatePrice(Order order, ListOrderItem items) { String memberLevel order.getMemberLevel(); BigDecimal discountRate discountMap.getOrDefault(memberLevel, BigDecimal.ONE); BigDecimal basePrice new BasePriceStrategy().calculatePrice(order, items); return basePrice.multiply(discountRate).setScale(2, RoundingMode.HALF_UP); } Override public String getStrategyName() { return 会员折扣; } } // 满减策略满N减M支持多档如满300减50满500减120 public class ThresholdDiscountStrategy implements PricingStrategy { // 多档满减规则[满额, 减额] 数组 private final Listint[] rules; public ThresholdDiscountStrategy(Listint[] rules) { this.rules rules; } Override public BigDecimal calculatePrice(Order order, ListOrderItem items) { BigDecimal basePrice new BasePriceStrategy().calculatePrice(order, items); BigDecimal discount BigDecimal.ZERO; // 按满额从高到低排序取最高可满足档位 rules.sort((a, b) - Integer.compare(b[0], a[0])); // 降序 for (int[] rule : rules) { if (basePrice.compareTo(BigDecimal.valueOf(rule[0])) 0) { discount BigDecimal.valueOf(rule[1]); break; } } return basePrice.subtract(discount).max(BigDecimal.ZERO); // 不低于0 } Override public String getStrategyName() { return 满减优惠; } }逻辑说明PricingStrategy接口将“计算什么”与“怎么计算”分离。BasePriceStrategy是基石其他策略都依赖它获取原始价格再叠加计算。ThresholdDiscountStrategy支持多档规则并自动选取最优档避免了if (price500) {...} else if (price300) {...}的硬编码嵌套。setScale(2, RoundingMode.HALF_UP)强制保留两位小数规避浮点精度问题——这是电商结算的硬性要求。3.2 构建策略上下文与组合策略支持// 策略上下文管理当前激活的策略 public class PricingContext { private PricingStrategy currentStrategy; public PricingContext(PricingStrategy strategy) { this.currentStrategy strategy; } // 运行时切换策略如营销活动开启时 public void setStrategy(PricingStrategy strategy) { this.currentStrategy strategy; } // 执行价格计算 public BigDecimal calculatePrice(Order order, ListOrderItem items) { if (currentStrategy null) { throw new IllegalStateException(未设置价格策略); } return currentStrategy.calculatePrice(order, items); } public String getCurrentStrategyName() { return currentStrategy ! null ? currentStrategy.getStrategyName() : 未设置; } } // 组合策略支持多个策略叠加如先会员折扣再满减 public class CompositePricingStrategy implements PricingStrategy { private final ListPricingStrategy strategies; public CompositePricingStrategy(ListPricingStrategy strategies) { this.strategies strategies; } Override public BigDecimal calculatePrice(Order order, ListOrderItem items) { BigDecimal price new BasePriceStrategy().calculatePrice(order, items); for (PricingStrategy strategy : strategies) { // 注意组合策略中每个策略都基于上一步结果计算 // 实际业务中需明确顺序如折扣在前满减在后 price strategy.calculatePrice(order, items); } return price.max(BigDecimal.ZERO); } Override public String getStrategyName() { return 组合策略( strategies.stream() .map(PricingStrategy::getStrategyName) .collect(Collectors.joining()) ); } }参数说明PricingContext是策略模式的“开关”它不参与计算只负责路由。CompositePricingStrategy解决了策略叠加问题——但要注意叠加顺序至关重要如满减后再打折 vs 折扣后再满减结果不同。实际项目中应在策略配置中显式声明执行顺序而非依赖List插入顺序。3.3 在订单服务中集成策略上下文// 订单服务核心结算逻辑与策略解耦 public class OrderService { // 策略上下文可被外部注入或配置 private PricingContext pricingContext; public OrderService() { // 默认使用基础价格策略 this.pricingContext new PricingContext(new BasePriceStrategy()); } // 允许运行时切换策略如根据订单会员等级自动匹配 public void setPricingStrategyForOrder(Order order) { if (GOLD.equals(order.getMemberLevel())) { pricingContext.setStrategy(new MemberDiscountStrategy()); } else if (order.getTotalAmount().compareTo(BigDecimal.valueOf(300)) 0) { // 满300减50 Listint[] rules Arrays.asList(new int[]{300, 50}); pricingContext.setStrategy(new ThresholdDiscountStrategy(rules)); } else { pricingContext.setStrategy(new BasePriceStrategy()); } } // 核心结算方法完全不关心具体策略实现 public BigDecimal calculateOrderTotal(Order order, ListOrderItem items) { System.out.println(【结算启动】使用策略 pricingContext.getCurrentStrategyName()); BigDecimal total pricingContext.calculatePrice(order, items); System.out.println(【结算完成】原始价 new BasePriceStrategy().calculatePrice(order, items) → 最终价 total); return total; } } // 订单实体类简化 public class Order { private String orderId; private String memberLevel; // 会员等级 private BigDecimal totalAmount; // 订单总金额计算前为null // 构造函数、getter/setter 略 } // 商品项实体类简化 public class OrderItem { private String itemId; private BigDecimal price; // 单价 private int quantity; // 数量 // 构造函数、getter/setter 略 } // 测试驱动验证策略切换效果 public class StrategyPatternDemo { public static void main(String[] args) { OrderService orderService new OrderService(); Order order new Order(); order.setOrderId(ORD-2024-001); order.setMemberLevel(GOLD); ListOrderItem items new ArrayList(); items.add(new OrderItem(DRESS-001, new BigDecimal(299.00), 1)); // 连衣裙299元 items.add(new OrderItem(SHIRT-002, new BigDecimal(199.00), 2)); // 衬衫199*2398元 System.out.println( 会员黄金等级订单 ); orderService.setPricingStrategyForOrder(order); orderService.calculateOrderTotal(order, items); System.out.println(\n 普通用户满300订单 ); order.setMemberLevel(NONE); orderService.setPricingStrategyForOrder(order); orderService.calculateOrderTotal(order, items); } }关键点OrderService.calculateOrderTotal()方法体只有3行却能支撑任意复杂的价格规则。新增“节日翻倍积分”策略只需实现PricingStrategy接口然后在setPricingStrategyForOrder()中添加判断逻辑即可。策略的“可配置化”是工程落地的关键——实际项目中策略选择逻辑应从硬编码迁移到配置中心如 Nacos、Apollo实现运维人员无需发版即可调整营销规则。4. 用观察者模式实现库存变更实时通知让“调拨申请”“售罄预警”自动触发不写轮询当A店向B店发起调拨申请或某款商品库存低于安全阈值时系统需要自动通知相关人员店长、采购员、系统管理员。传统做法是在调拨/销售方法末尾硬编码调用sendEmail()、sendSMS()导致业务逻辑与通知逻辑强耦合。观察者模式将“谁来通知”和“通知什么”解耦库存上下文作为被观察者Subject各类通知服务作为观察者Observer当库存变更时上下文遍历通知所有注册的观察者。4.1 定义观察者接口与具体通知实现// 观察者接口所有监听库存变更的服务必须实现 public interface InventoryObserver { // 当库存发生变更时被调用 void onInventoryChanged(InventoryEvent event); // 获取观察者名称用于日志 String getObserverName(); } // 邮件通知观察者 public class EmailNotificationObserver implements InventoryObserver { private final String adminEmail; public EmailNotificationObserver(String adminEmail) { this.adminEmail adminEmail; } Override public void onInventoryChanged(InventoryEvent event) { String subject 【库存告警】 event.getItemId() 在 event.getLocation() 状态变更; String body String.format( 时间%s\n 事件%s\n 原状态%s → 新状态%s\n 当前库存%d\n 操作人%s, new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date()), event.getEventType(), event.getOldState(), event.getNewState(), event.getCurrentStock(), event.getOperator() ); // 实际项目中调用邮件发送SDK如JavaMail、SendGrid System.out.println( 已发送邮件至 adminEmail \n body); } Override public String getObserverName() { return 邮件通知; } } // 短信通知观察者模拟 public class SMSNotificationObserver implements InventoryObserver { private final String adminPhone; public SMSNotificationObserver(String adminPhone) { this.adminPhone adminPhone; } Override public void onInventoryChanged(InventoryEvent event) { String message String.format( 【服装系统】%s%s 库存变更%s→%s余%d件, event.getItemId(), event.getLocation(), event.getOldState(), event.getNewState(), event.getCurrentStock() ); // 实际项目中调用短信网关API System.out.println( 已发送短信至 adminPhone message); } Override public String getObserverName() { return 短信通知; } } // 日志审计观察者必选记录所有变更 public class AuditLogObserver implements InventoryObserver { Override public void onInventoryChanged(InventoryEvent event) { System.out.println( 审计日志 event.getEventType() | event.getItemId() event.getLocation() | event.getOldState() → event.getNewState() | 操作人 event.getOperator()); } Override public String getObserverName() { return 审计日志; } }逻辑说明每个观察者只关注自己职责——邮件发详细内容短信发简讯日志记全字段。onInventoryChanged()方法接收统一的InventoryEvent对象确保观察者不依赖具体业务类降低耦合。AuditLogObserver是基础设施层观察者应始终启用为后续排查问题提供依据。4.2 构建被观察者库存上下文与事件对象// 库存变更事件承载通知所需的所有数据 public class InventoryEvent { private final String itemId; private final String location; private final String eventType; // SALE, STOCK_ADJUST, STATE_CHANGE private final String oldState; private final String newState; private final int currentStock; private final String operator; // 操作人ID private final long timestamp; public InventoryEvent(String itemId, String location, String eventType, String oldState, String newState, int currentStock, String operator) { this.itemId itemId; this.location location; this.eventType eventType; this.oldState oldState; this.newState newState; this.currentStock currentStock; this.operator operator; this.timestamp System.currentTimeMillis(); } // Getter 方法略 public String getItemId() { return itemId; } public String getLocation() { return location; } public String getEventType() { return eventType; } public String getOldState() { return oldState; } public String getNewState() { return newState; } public int getCurrentStock() { return currentStock; } public String getOperator() { return operator; } public long getTimestamp() { return timestamp; } } // 增强版库存上下文支持观察者注册与通知 public class ObservableInventoryContext extends InventoryContext { private final ListInventoryObserver observers new ArrayList(); public ObservableInventoryContext(String itemId, int initialStock, String location) { super(itemId, initialStock, location); } // 注册观察者 public void addObserver(InventoryObserver observer) { if (!observers.contains(observer)) { observers.add(observer); System.out.println(✅ 已注册观察者 observer.getObserverName()); } } // 移除观察者 public void removeObserver(InventoryObserver observer) { observers.remove(observer); } // 通知所有观察者重写父类状态变更方法 Override public void setState(InventoryState newState) { String oldState this.getStateName(); super.setState(newState); // 先执行状态变更 // 再发布事件 InventoryEvent event new InventoryEvent( getItemId(), getLocation(), STATE_CHANGE, oldState, newState.getStateName(), getStock(), SYSTEM // 系统自动触发 ); notifyObservers(event); } // 通知所有观察者新增库存扣减事件 public void onStockDecreased(int quantity, String operator) { int newStock getStock(); InventoryEvent event new InventoryEvent( getItemId(), getLocation(), SALE, getStateName(), getStateName(), newStock, operator ); notifyObservers(event); } // 通用通知方法 private void notifyObservers(InventoryEvent event) { System.out.println( 开始通知 observers.size() 个观察者...); for (InventoryObserver observer : observers) { try { observer.onInventoryChanged(event); } catch (Exception e) { // 观察者异常不应阻断主流程 System.err.println(⚠️ 观察者 observer.getObserverName() 通知失败 e.getMessage()); } } } }参数说明ObservableInventoryContext继承自InventoryContext复用其状态机能力同时增加观察者管理。notifyObservers()中的异常捕获是关键——某个观察者如邮件服务宕机不能导致库存扣减失败。onStockDecreased()方法暴露给外部调用用于销售、调拨等业务操作后手动触发通知比在sell()方法里硬编码更灵活。4.3 在库存服务中配置观察者并触发通知// 增强版库存服务初始化观察者并绑定 public class ObservableInventoryService extends InventoryService { public ObservableInventoryService() { super(); // 初始化时为所有库存项注册观察者 initObservers(); } private void initObservers() { // 为所有库存项添加审计日志观察者必须 for (InventoryContext context : inventoryMap.values()) { if (context instanceof ObservableInventoryContext) { ((ObservableInventoryContext) context).addObserver(new AuditLogObserver()); } } // 为特定高价值商品添加邮件短信告警示例连衣裙 ObservableInventoryContext dressContextA (ObservableInventoryContext) inventoryMap.get(DRESS-001STORE-A); if (dressContextA ! null) { dressContextA.addObserver(new EmailNotificationObserver(managerstore-a.com)); dressContextA.addObserver(new SMSNotificationObserver(13800138000)); } } // 重写下单方法触发库存变更通知 Override public boolean processOrder(String itemId, String storeId) { String key itemId storeId; ObservableInventoryContext context (ObservableInventoryContext) inventoryMap.get(key); if (context null) { System.out.println(错误未找到商品 itemId 在门店 storeId); return false; } try { context.sell(); // 扣减成功后手动触发销售事件通知含操作人 context.onStockDecreased(1, USER-12345); // 模拟用户ID return true; } catch (IllegalStateException e) { System.out.println(订单失败 e.getMessage()); return false; } } } // 测试驱动验证观察者通知链 public class ObserverPatternDemo { public static void main(String[] args) { ObservableInventoryService service new ObservableInventoryService(); System.out.println(\n A店售出1件连衣裙触发邮件短信日志 ); service.processOrder(DRESS-001, STORE-A); } }关键点观察者模式的价值在于“松耦合”和“可扩展”。当需要新增“企业微信机器人告警”时只需编写WeComNotificationObserver并在initObservers()中注册无需修改ObservableInventoryContext或任何业务方法。processOrder()方法依然只做一件事调用context.sell()和context.onStockDecreased()通知逻辑完全由观察者自治。这种设计让系统具备了应对未来通知渠道变化的弹性。5. 避坑指南设计模式落地时最常踩的5个血泪坑设计模式不是银弹生搬硬套反而会让代码更难维护。以下是我在指导多个模拟项目X过程中学生反复踩中的典型陷阱每一条都附带真实复现步骤和修复方案。5.1 现象状态模式中新增状态后所有已有状态类都要修改handleXXX()方法原因在InventoryState接口中定义了所有可能的操作handleList,handleSell,handleUnlist但并非每个状态都支持全部操作。当新增一个操作如handleFreeze()时编译器强制要求所有6个状态类都实现该方法哪怕其中5个状态根本不允许冻结。解决采用“空对象模式”或“默认实现”。将接口改为抽象类为不支持的操作提供默认空实现public abstract class AbstractInventoryState implements InventoryState { Override public void handleList(InventoryContext context) { throw new UnsupportedOperationException(当前状态不支持上架操作); } // 其他方法同理... }这样新增操作只需在抽象类中添加默认方法已有状态类无需改动只在需要支持的子类中重写即可。5.2 现象策略模式中组合策略Composite计算结果错误满减没生效原因CompositePricingStrategy的calculatePrice()方法中每个策略都基于BasePriceStrategy的原始价格计算而非上一个策略的结果。例如先算会员价299×0.85254.15再算满减254.15满300不满足满减失效导致满减未触发。解决修正组合策略逻辑确保链式计算public BigDecimal calculatePrice(Order order, ListOrderItem items) { BigDecimal price new BasePriceStrategy().calculatePrice(order, items); for (PricingStrategy strategy : strategies) { // 关键传入当前price而非原始items price strategy.calculatePrice(order, items); // ❌ 错误仍用原始items // 正确做法需策略支持“基于当前价格计算”或重构为责任链模式 } return price; }更优解放弃CompositePricingStrategy改用责任链模式Chain of Responsibility每个处理器决定是否处理及是否继续传递。5.3 现象观察者模式中短信通知偶尔丢失日志显示“观察者通知失败”原因notifyObservers()中的异常捕获过于宽泛SMSNotificationObserver内部调用第三方短信API时抛出NetworkException但被catch (Exception e)吞掉仅打印错误日志未做重试或告警。解决分层异常处理。观察者内部应捕获网络异常并记录详细堆栈同时向上抛出业务异常上下文层捕获后对关键观察者如短信启动异步重试// 在 notifyObservers() 中 if (observer instanceof SMSNotificationObserver) { // 启动异步重试任务如用 ScheduledExecutorService retrySMSLater(event, (SMSNotificationObserver) observer); } else { observer.onInventoryChanged(event); }5.4 现象工厂模式创建服装对象时传入参数过多品牌、季节、尺码、颜色、材质...构造函数爆炸原因过度追求“一个工厂创建所有服装”将所有属性塞进工厂方法参数违背单一职责。解决采用“建造者模式Builder”配合工厂。工厂只负责返回对应类型的 Builder由 Builder 逐步设置属性public class ClothingFactory { public static DressBuilder createDress() { return new DressBuilder(); } public static ShirtBuilder createShirt() { return new ShirtBuilder(); } } // 使用ClothingFactory.createDress().brand(ZARA).season(SUMMER).size(M).build();工厂退化为“类型路由”复杂对象本文还有配套的精品资源点击获取