Using Strategy Pattern in Ruby
By Tanmay
Strategy pattern is a behavioral pattern used when there is a need to choose an algorithm at runtime. It’s an excellent example of the open/closed principle: software entities should be open for extension, but closed for modification.
A Practical Example: AI Chess Player
Consider building an AI chess player with three difficulty levels. Each level needs a different algorithm for calculating the next move.
Architecture
- AiStrategy — abstract base class defining the interface
- HardLevelStrategy — implements advanced move calculation
- MediumLevelStrategy — implements moderate difficulty
- EasyLevelStrategy — implements simple move selection
- ChessGame — the executor class that accepts a strategy at runtime
The Base Strategy
The base strategy class raises NotImplementedError for unimplemented methods, ensuring all concrete strategies implement the required interface:
class AiStrategy
def next_move
raise NotImplementedError
end
end
Concrete Strategies
Each concrete strategy overrides the next_move method with its own algorithm. The key insight is that the ChessGame class doesn’t need to know which strategy it’s using — it just calls next_move.
The Power of Open/Closed
Need to add a new RandomizedStrategy? Simply create a new class inheriting from AiStrategy. No modifications to existing code are needed. This is the open/closed principle in action.
Pattern Components
- AbstractStrategy — defines method contracts
- Concrete Strategies — multiple implementations of the interface
- Executor — selects and uses strategies at runtime
Conclusion
The Strategy pattern keeps your code clean, extensible, and maintainable. When you find yourself writing complex conditional logic to switch between algorithms, consider refactoring to the Strategy pattern.