
Rust 策略模式讲解和代码示例
策略是一种行为设计模式, 它将一组行为转换为对象, 并使其在原始上下文对象内部能够相互替换。
原始对象被称为上下文, 它包含指向策略对象的引用并将执行行为的任务分派给策略对象。 为了改变上下文完成其工作的方式, 其他对象可以使用另一个对象来替换当前链接的策略对象。
Conceptual Example
A conceptual Strategy example via traits.
conceptual.rs
/// Defines an injectable strategy for building routes.
trait RouteStrategy {
fn build_route(&self, from: &str, to: &str);
}
struct WalkingStrategy;
impl RouteStrategy for WalkingStrategy {
fn build_route(&self, from: &str, to: &str) {
println!("Walking route from {} to {}: 4 km, 30 min", from, to);
}
}
struct PublicTransportStrategy;
impl RouteStrategy for PublicTransportStrategy {
fn build_route(&self, from: &str, to: &str) {
println!(
"Public transport route from {} to {}: 3 km, 5 min",
from, to
);
}
}
struct Navigator<T: RouteStrategy> {
route_strategy: T,
}
impl<T: RouteStrategy> Navigator<T> {
pub fn new(route_strategy: T) -> Self {
Self { route_strategy }
}
pub fn route(&self, from: &str, to: &str) {
self.route_strategy.build_route(from, to);
}
}
fn main() {
let navigator = Navigator::new(WalkingStrategy);
navigator.route("Home", "Club");
navigator.route("Club", "Work");
let navigator = Navigator::new(PublicTransportStrategy);
navigator.route("Home", "Club");
navigator.route("Club", "Work");
}
Output
Walking route from Home to Club: 4 km, 30 min Walking route from Club to Work: 4 km, 30 min Public transport route from Home to Club: 3 km, 5 min Public transport route from Club to Work: 3 km, 5 min
Functional approach
Functions and closures simplify Strategy implementation as you can inject behavior right into the object without complex interface definition.
It seems that Strategy is often implicitly and widely used in the modern development with Rust, e.g. it's just like iterators work:
let a = [0i32, 1, 2];
let mut iter = a.iter().filter(|x| x.is_positive());
functional.rs
type RouteStrategy = fn(from: &str, to: &str);
fn walking_strategy(from: &str, to: &str) {
println!("Walking route from {} to {}: 4 km, 30 min", from, to);
}
fn public_transport_strategy(from: &str, to: &str) {
println!(
"Public transport route from {} to {}: 3 km, 5 min",
from, to
);
}
struct Navigator {
route_strategy: RouteStrategy,
}
impl Navigator {
pub fn new(route_strategy: RouteStrategy) -> Self {
Self { route_strategy }
}
pub fn route(&self, from: &str, to: &str) {
(self.route_strategy)(from, to);
}
}
fn main() {
let navigator = Navigator::new(walking_strategy);
navigator.route("Home", "Club");
navigator.route("Club", "Work");
let navigator = Navigator::new(public_transport_strategy);
navigator.route("Home", "Club");
navigator.route("Club", "Work");
let navigator = Navigator::new(|from, to| println!("Specific route from {} to {}", from, to));
navigator.route("Home", "Club");
navigator.route("Club", "Work");
}
Output
Walking route from Home to Club: 4 km, 30 min Walking route from Club to Work: 4 km, 30 min Public transport route from Home to Club: 3 km, 5 min Public transport route from Club to Work: 3 km, 5 min Specific route from Home to Club Specific route from Club to Work