如何通过 switch 与 enum 结合实现解耦的 Strategy 模式应用?
- 内容介绍
- 文章标签
- 相关推荐
本文共计794个文字,预计阅读时间需要4分钟。
直接使用enum实现策略接口,再配合+
让枚举直接实现策略接口
Java 中的 enum 天然支持实现接口、定义抽象方法和提供具体实现,无需为每个策略新建类。
- 定义统一策略接口,例如 PaymentStrategy,含
pay(double amount)方法 - 声明枚举 PaymentMethod,implements PaymentStrategy
- 每个枚举常量(如
CREDIT_CARD、PAYPAL)在声明时直接覆写pay方法,内联具体逻辑 - 上下文(Context)只依赖接口,传入
PaymentMethod.CREDIT_CARD即可调用,完全屏蔽实现细节
用 switch 做编译期穷尽性保障与降级处理
switch 不用来写主流程,而是作为“安全网”——检查是否所有枚举值都被策略覆盖,或在特殊场景(如灰度、调试)中动态干预。
- 在工厂方法或配置加载处,用 switch 遍历
PaymentMethod.values(),确保每个值都注册到策略映射表中 - 在日志或监控模块中,用 switch 将枚举转为可读描述(如
CREDIT_CARD → "信用卡"),便于排查 - default 分支不空置,抛出
AssertionError或记录告警,迫使新增枚举时必须显式处理 - 若需运行时切换策略行为(如测试环境强制走模拟支付),可在 switch 中注入 mock 实例,而非修改枚举本身
结合静态字段与延迟初始化提升性能
枚举实例是单例且线程安全,但复杂策略可能带状态或外部依赖。这时可将策略逻辑下沉为静态内部类或懒加载字段。
- 枚举常量不直接写大段业务代码,而是引用一个私有静态策略类(如
private static final CreditCardProcessor PROCESSOR = new CreditCardProcessor();) - 需要 Spring 管理的 Bean 时,通过
ApplicationContext按名称获取,枚举中只存 bean 名(如private final String beanName = "creditCardPaymentService";) - 避免在枚举构造器中执行耗时操作,把初始化推迟到首次
pay()调用时
规避常见陷阱
这种写法简洁,但容易因小疏忽引入隐性耦合。
- 不要在枚举方法里硬编码数据库连接或 HTTP 客户端——应通过参数传入或由上层注入
- 避免枚举方法间相互调用形成环路,尤其当策略存在继承关系时
- 若策略需共享状态(如计数器、缓存),使用
static字段要加锁或改用ConcurrentHashMap,不能依赖枚举单例的线程安全性 - 对外暴露的枚举类型不应包含敏感字段(如密钥、令牌),策略实现应通过配置中心或环境变量注入
本文共计794个文字,预计阅读时间需要4分钟。
直接使用enum实现策略接口,再配合+
让枚举直接实现策略接口
Java 中的 enum 天然支持实现接口、定义抽象方法和提供具体实现,无需为每个策略新建类。
- 定义统一策略接口,例如 PaymentStrategy,含
pay(double amount)方法 - 声明枚举 PaymentMethod,implements PaymentStrategy
- 每个枚举常量(如
CREDIT_CARD、PAYPAL)在声明时直接覆写pay方法,内联具体逻辑 - 上下文(Context)只依赖接口,传入
PaymentMethod.CREDIT_CARD即可调用,完全屏蔽实现细节
用 switch 做编译期穷尽性保障与降级处理
switch 不用来写主流程,而是作为“安全网”——检查是否所有枚举值都被策略覆盖,或在特殊场景(如灰度、调试)中动态干预。
- 在工厂方法或配置加载处,用 switch 遍历
PaymentMethod.values(),确保每个值都注册到策略映射表中 - 在日志或监控模块中,用 switch 将枚举转为可读描述(如
CREDIT_CARD → "信用卡"),便于排查 - default 分支不空置,抛出
AssertionError或记录告警,迫使新增枚举时必须显式处理 - 若需运行时切换策略行为(如测试环境强制走模拟支付),可在 switch 中注入 mock 实例,而非修改枚举本身
结合静态字段与延迟初始化提升性能
枚举实例是单例且线程安全,但复杂策略可能带状态或外部依赖。这时可将策略逻辑下沉为静态内部类或懒加载字段。
- 枚举常量不直接写大段业务代码,而是引用一个私有静态策略类(如
private static final CreditCardProcessor PROCESSOR = new CreditCardProcessor();) - 需要 Spring 管理的 Bean 时,通过
ApplicationContext按名称获取,枚举中只存 bean 名(如private final String beanName = "creditCardPaymentService";) - 避免在枚举构造器中执行耗时操作,把初始化推迟到首次
pay()调用时
规避常见陷阱
这种写法简洁,但容易因小疏忽引入隐性耦合。
- 不要在枚举方法里硬编码数据库连接或 HTTP 客户端——应通过参数传入或由上层注入
- 避免枚举方法间相互调用形成环路,尤其当策略存在继承关系时
- 若策略需共享状态(如计数器、缓存),使用
static字段要加锁或改用ConcurrentHashMap,不能依赖枚举单例的线程安全性 - 对外暴露的枚举类型不应包含敏感字段(如密钥、令牌),策略实现应通过配置中心或环境变量注入

