This is what I came up with: Playground
It uses dynamic dispatch, but you could make it generic I guess. The advantage is that the strategy can be selected at runtime, but the disadvantage is that the implementation trait must be object safe.
The main idea is to use a struct instead of a trait for the TextFormatter
:
// A struct that can format something with different strategies
pub struct TextFormatter<'a> {
strategy: &'a dyn TextFormatterImpl,
}
The trait implementing the strategies is private, so it can't be implemented in other modules:
trait TextFormatterImpl {
fn bold_impl(&self, f: &mut Formatter<'_>, value: &dyn Display) -> fmt::Result;
fn strike_impl(&self, f: &mut Formatter<'_>, value: &dyn Display) -> fmt::Result;
}
EDIT: Here's a Playground using generics.