设计模式 23 种实战辨析:从工厂到策略,5 大高频模式 UML 类图绘制要点

设计模式 23 种实战辨析:从工厂到策略,5 大高频模式 UML 类图绘制要点 设计模式23种实战辨析从工厂到策略5大高频模式UML类图绘制要点1. 为什么UML类图是设计模式的核心表达在软件工程领域设计模式是解决特定问题的经典方案模板而UML类图则是描述这些方案最直观的设计蓝图。对于开发者而言能够准确绘制设计模式的UML类图意味着深入理解模式本质类关系揭示了模式的核心机制清晰传达设计意图图示比文字描述更高效准确应对技术面试考核90%的设计模式面试题涉及绘图提升代码设计能力从模式应用到架构思维的跃迁常见绘图误区对比表错误类型工厂方法模式典型错误正确表达方式角色混淆将具体工厂与产品直接关联通过抽象工厂接口隔离关系错位用实现箭头表示创建关系使用依赖虚线箭头缺失关键元素忽略工厂方法返回类型明确标注createProduct():Product提示绘制类图时建议先标注模式中的各个角色Creator、Product等再建立关系最后补充方法签名这种三步法可避免结构性错误。2. 工厂三剑客从简单工厂到抽象工厂2.1 工厂方法模式绘图要点startuml skinparam classAttributeIconSize 0 abstract class Creator { factoryMethod(): Product someOperation() } abstract class Product { doStuff() } class ConcreteCreatorA { factoryMethod(): Product } class ConcreteProductA { doStuff() } Creator |-- ConcreteCreatorA Product |-- ConcreteProductA ConcreteCreatorA .. ConcreteProductA note right of Creator::factoryMethod 返回类型必须为Product抽象类型 而非具体产品类 end note enduml关键标注规范工厂方法应声明为抽象方法斜体表示返回类型标注为抽象产品类型具体工厂与具体产品间用依赖虚线箭头产品接口需包含业务方法签名2.2 抽象工厂模式进阶绘制startuml skinparam classAttributeIconSize 0 interface AbstractFactory { createProductA(): AbstractProductA createProductB(): AbstractProductB } class ConcreteFactory1 { createProductA(): AbstractProductA createProductB(): AbstractProductB } interface AbstractProductA { usefulFunctionA() } interface AbstractProductB { usefulFunctionB() } class ProductA1 { usefulFunctionA() } class ProductB1 { usefulFunctionB() } AbstractFactory |.. ConcreteFactory1 AbstractProductA |.. ProductA1 AbstractProductB |.. ProductB1 ConcreteFactory1 .. ProductA1 ConcreteFactory1 .. ProductB1 note top of AbstractFactory 每个工厂方法对应产品等级结构 一个产品族包含多个等级结构产品 end note enduml产品族与等级结构对比表维度产品族产品等级结构关系横向关联同一工厂创建纵向继承同一产品类型UML表达工厂到产品的依赖簇产品接口的实现关系变化影响新增工厂不影响现有代码新增产品需修改所有工厂典型案例macOS组件 vs Windows组件按钮在不同OS下的实现3. 行为型模式的双子星策略与状态3.1 策略模式动态切换算法// 典型策略模式代码结构 interface Strategy { void execute(); } class ConcreteStrategyA implements Strategy { public void execute() { System.out.println(使用算法A); } } class Context { private Strategy strategy; public void setStrategy(Strategy s) { this.strategy s; } public void executeStrategy() { strategy.execute(); } }策略模式vs状态模式辨析特性策略模式状态模式转换机制客户端主动切换状态间自动转换对象关系策略相互独立状态知晓其他状态存在方法参数通常无状态常包含Context参数适用场景算法可互相替换对象行为随状态改变类图差异点Context持有策略引用状态持有Context反向引用3.2 状态模式绘图注意事项startuml skinparam classAttributeIconSize 0 class Context { -state: State request() changeState(s:State) } interface State { handle(c:Context) } class ConcreteStateA { handle(c:Context) } class ConcreteStateB { handle(c:Context) } Context o-- State State |.. ConcreteStateA State |.. ConcreteStateB note left of Context::request 委托给当前状态对象处理 通常包含状态转换逻辑 end note enduml状态转换的三种实现方式状态枚举法适合简单场景class TrafficLight: def __init__(self): self.state RED def change(self): if self.state RED: self.state GREEN elif self.state GREEN: self.state YELLOW else: self.state RED状态表驱动法可配置性强const stateMachine { RED: { timeout: 30, next: GREEN }, GREEN: { timeout: 45, next: YELLOW }, YELLOW: { timeout: 5, next: RED } };状态模式法面向对象标准实现public interface State { void handle(Context ctx); }4. 观察者模式的动静分离之道4.1 推模型与拉模型对比实现推模型类图要素Subject维护观察者列表使用聚合关系观察者接口定义update(data:Object)方法具体Subject在notify时传递完整数据拉模型实现差异startuml skinparam classAttributeIconSize 0 interface Observer { update(s:Subject) } class ConcreteObserver { -subject: Subject update(s:Subject) } interface Subject { attach(o:Observer) detach(o:Observer) notify() getState() } Subject |.. ConcreteSubject Subject o-- Observer Observer |.. ConcreteObserver ConcreteObserver -- ConcreteSubject note right of Observer::update 观察者主动从Subject拉取数据 而非被动接收推送数据 end note enduml两种模型的选择标准考量因素推模型优势拉模型优势网络带宽不适合数据量大场景按需获取节省带宽观察者多样性需统一数据格式各观察者获取不同属性实时性要求立即传递最新状态可能存在状态获取延迟耦合度Subject需知观察者数据结构Subject无需知观察者需求4.2 JDK内置观察者实现要点// 使用java.util.Observable的注意事项 public class WeatherData extends Observable { private float temperature; public void measurementsChanged() { setChanged(); // 必须调用此方法 notifyObservers(); // 拉模型实现 } // 提供getter方法供观察者拉取数据 public float getTemperature() { return temperature; } } public class CurrentConditionsDisplay implements Observer { public void update(Observable o, Object arg) { if (o instanceof WeatherData) { WeatherData wd (WeatherData)o; float temp wd.getTemperature(); // 更新显示逻辑 } } }setChanged()方法的设计意义提供缓冲机制避免频繁更新支持条件通知仅当数据确实变化时允许在通知前进行多个属性更新5. 模式选择决策树与综合应用5.1 五大模式快速决策指南graph TD A[需要创建对象?] --|是| B{创建逻辑复杂?} B --|简单| C[简单工厂] B --|复杂| D{产品族存在?} D --|是| E[抽象工厂] D --|否| F[工厂方法] A --|否| G{行为随状态变?} G --|是| H[状态模式] G --|否| I{算法需要切换?} I --|是| J[策略模式] I --|否| K{需要事件通知?} K --|是| L[观察者模式]5.2 综合案例电商促销系统设计需求场景不同促销策略满减、折扣、赠品策略可动态切换促销活动状态管理未开始/进行中/已结束活动变化通知商户系统UML混合模式解决方案startuml skinparam classAttributeIconSize 0 class PromotionManager { -strategy: PromotionStrategy -state: PromotionState -observers: ListMerchantObserver setStrategy() applyPromotion() changeState() notifyMerchants() } interface PromotionStrategy { applyDiscount() } class DiscountStrategy { applyDiscount() } class FullReductionStrategy { applyDiscount() } interface PromotionState { handle(manager:PromotionManager) } class PreparingState { handle() } class ActiveState { handle() } interface MerchantObserver { onPromotionUpdate() } PromotionManager o-- PromotionStrategy PromotionManager o-- PromotionState PromotionManager o-- MerchantObserver PromotionStrategy |.. DiscountStrategy PromotionStrategy |.. FullReductionStrategy PromotionState |.. PreparingState PromotionState |.. ActiveState MerchantObserver |.. SMSNotifier MerchantObserver |.. EmailNotifier note bottom of PromotionManager 同时组合了策略模式、状态模式 和观察者模式三种设计模式 end note enduml模式协作关系分析策略模式处理促销算法变化状态模式管理活动生命周期观察者模式实现商户通知三种模式通过PromotionManager协调性能优化建议使用线程安全的集合存储观察者策略对象通常可设计为无状态享元模式状态转换考虑使用状态表配置化