How do I implement the strategy pattern in EK9?
← Design Patterns and Idioms · Ref: Q214
EK9 implements the strategy pattern using abstract functions and dynamic function implementations. Pass different function instances to swap behavior.
ABSTRACT FUNCTION AS STRATEGY
Define the strategy interface as an abstract function:
Formatter as abstract function -> item as String <- rtn as String?
DYNAMIC IMPLEMENTATIONS
Create concrete strategies with dynamic functions:
upperFormatter <- () is Formatter as function rtn: item.upperCase() lowerFormatter <- () is Formatter as function rtn: item.lowerCase()
PROCESSOR WITH STRATEGY
Pass the strategy as a parameter:
Processor
process()
->
formatter as Formatter
text as String
<- rtn as String: formatter(text)
SWAPPING STRATEGIES
Use different formatters without changing Processor:
processor.process(upperFormatter, "hello") processor.process(lowerFormatter, "HELLO")
See Q57 for strategy without subclassing. See Q52 for dynamic functions. See Q55 for function delegation. See Q210 for trait delegation as an alternative to function strategies.
Example
defines module qa.patterns.strategy defines function Formatter() as abstract -> item as String <- rtn as String? defines class TextProcessor process() -> formatter as Formatter text as String <- rtn as String: formatter(text) default operator ? defines program StrategyPatternDemo() stdout <- Stdout() // === DYNAMIC FUNCTION STRATEGIES === upperFormatter <- () is Formatter as function rtn: item.upperCase() lowerFormatter <- () is Formatter as function rtn: item.lowerCase() // === PROCESSOR USES STRATEGY === textProcessor <- TextProcessor() upper <- textProcessor.process(upperFormatter, "hello world") stdout.println(`Upper: ${upper}`) lower <- textProcessor.process(lowerFormatter, "HELLO WORLD") stdout.println(`Lower: ${lower}`) // === SWAP STRATEGIES FREELY === stdout.println("Strategy pattern: swap behavior via function parameters")
Common mistakes
E07110 — Abstract functions define a strategy interface with no implementation. Using 'as open' instead of 'as abstract' triggers E07110 because 'open' is for functions with a body that can be overridden, not for bodyless declarations. See ek9 -h E07110 for details.
Incorrect:
Formatter() as open
Correct:
Formatter() as abstract
Other ways to ask this
- How do I swap algorithms at runtime in EK9?
- How do I use functions as strategies in EK9?
- How do I inject behavior via function parameters in EK9?
Coming from another language?
Java: Strategy interface with implementing classes. Python: pass functions directly (first-class). Rust: trait objects or closures. Go: function types. Kotlin: function types or interface implementations. EK9: abstract function as strategy interface, dynamic functions as implementations.
Keywords: function, delegate, behavior, strategy, algorithm, design, inject, flexible, swap, pattern, idiom