Ruby策略模式优化:避免无关方法继承的DRY实现问询
Great question—this is a classic case where overusing inheritance can lead to bloated base classes and unnecessary method exposure, which is definitely a code smell we want to avoid. Let’s walk through a few clean, Ruby-idiomatic solutions tailored to your scenario:
方案1:使用模块(Module)实现组合式复用
Ruby’s modules are perfect for extracting shared behavior that only applies to a subset of your strategy classes. Instead of polluting the base class with add_hot_sauce, we’ll wrap this method in a module and "mix it in" only where it’s needed.
# 提取共享的加辣酱行为到模块 module HotSauceable def add_hot_sauce # 这里是你的具体实现逻辑 puts "Drizzling spicy hot sauce!" end end # 基类只保留所有策略共有的核心方法 class FoodStrategy def prepare_food raise NotImplementedError, "Subclasses must implement #prepare_food" end end # 需要加辣酱的策略混入模块 class FoodStrategies::Taco < FoodStrategy include HotSauceable def prepare_food add_hot_sauce # 其他制作taco的逻辑 puts "Assembling crunchy taco!" end end class FoodStrategies::Burrito < FoodStrategy include HotSauceable def prepare_food add_hot_sauce # 其他制作burrito的逻辑 puts "Wrapping hearty burrito!" end end # 不需要辣酱的策略直接继承基类,无多余方法 class FoodStrategies::Cereal < FoodStrategy def prepare_food # 制作麦片的逻辑 puts "Pouring milk over cereal!" end end
优点:
- 遵循组合优于继承的原则,避免了不必要的继承层次
- 每个策略类只包含它实际需要的行为,符合单一职责原则
- 模块可以轻松复用在其他需要加辣酱的类中,扩展性强
方案2:拆分基类形成层次结构
If add_hot_sauce is part of a larger set of shared behaviors for your spicy food strategies, you can split your base class into a two-level hierarchy:
# 最基础的基类,包含所有策略通用的方法 class BaseFoodStrategy def prepare_food raise NotImplementedError, "Subclasses must implement #prepare_food" end end # 专门为需要加辣酱的策略创建子类 class SpicyFoodStrategy < BaseFoodStrategy def add_hot_sauce puts "Drizzling spicy hot sauce!" end end # 辣味策略继承自SpicyFoodStrategy class FoodStrategies::Taco < SpicyFoodStrategy def prepare_food add_hot_sauce puts "Assembling crunchy taco!" end end class FoodStrategies::Burrito < SpicyFoodStrategy def prepare_food add_hot_sauce puts "Wrapping hearty burrito!" end end # 非辣味策略直接继承BaseFoodStrategy class FoodStrategies::Cereal < BaseFoodStrategy def prepare_food puts "Pouring milk over cereal!" end end
优点:
- 清晰划分了策略的层次,适合有多个共享行为的场景
- 保留了继承的语义,让代码意图更明确
- 避免了无用方法的跨类继承
注意: 这个方案更适合当你有一组相关的共享方法(不止add_hot_sauce),否则模块方案会更轻量灵活。
为什么不把add_hot_sauce放在基类?
Putting add_hot_sauce in the base class would force FoodStrategies::Cereal to inherit a method it never uses. This violates the Interface Segregation Principle (clients shouldn’t depend on interfaces they don’t need) and creates a "fat base class" that becomes harder to maintain as your strategy set grows.
内容的提问来源于stack exchange,提问作者Argus9

