Skip to content

Instantly share code, notes, and snippets.

@blogscot
Last active April 27, 2018 18:01
Show Gist options
  • Save blogscot/0b48f242c5ed84786bfd48cc2221a836 to your computer and use it in GitHub Desktop.
Save blogscot/0b48f242c5ed84786bfd48cc2221a836 to your computer and use it in GitHub Desktop.
Visitor Pattern Example in Rust
///
/// Each car element accepts a visitor.
///
trait CarElement {
fn accept(&self, visitor: &CarElementVisitor);
}
///
/// Each visitor must deal with each element of a car.
///
trait CarElementVisitor {
fn visit_car(&self, element: &Car);
fn visit_body(&self, element: &Body);
fn visit_engine(&self, element: &Engine);
fn visit_wheel(&self, element: &Wheel);
}
///
/// A car is a bunch of `elements`.
struct Car {
pub elements: Vec<Box<CarElement>>,
message: String,
}
impl Car {
///
/// Construct a new car.
///
fn new() -> Self {
let engine: Box<CarElement> = Box::new(Engine {
message: "Checking the engine.".to_string(),
});
let body: Box<CarElement> = Box::new(Body {
message: "Examining the body.".to_string(),
});
let wheel_positions = ["front right", "front left", "back right", "back left"];
let wheels: Vec<Box<CarElement>> = wheel_positions
.iter()
.map(|position| {
Box::new(Wheel {
position: position.to_string(),
})
} as Box<CarElement>)
.collect();
let mut elements = vec![engine, body];
elements.extend(wheels);
Car {
elements,
message: "Starting my car.".to_string(),
}
}
}
///
/// Treat a car like any car element, that is,
/// it can be visited!
///
impl CarElement for Car {
fn accept(&self, visitor: &CarElementVisitor) {
for element in &self.elements {
element.accept(visitor);
}
visitor.visit_car(self);
}
}
struct Body {
message: String,
}
impl CarElement for Body {
fn accept(&self, visitor: &CarElementVisitor) {
visitor.visit_body(self);
}
}
struct Engine {
message: String,
}
impl CarElement for Engine {
fn accept(&self, visitor: &CarElementVisitor) {
visitor.visit_engine(self);
}
}
struct Wheel {
position: String,
}
impl CarElement for Wheel {
fn accept(&self, visitor: &CarElementVisitor) {
visitor.visit_wheel(self);
}
}
///
/// Welcome our first visitor.
///
struct PrintVisitor {}
impl CarElementVisitor for PrintVisitor {
fn visit_car(&self, element: &Car) {
println!("{}", element.message);
}
fn visit_body(&self, element: &Body) {
println!("{}", element.message);
}
fn visit_engine(&self, element: &Engine) {
println!("{}", element.message);
}
fn visit_wheel(&self, element: &Wheel) {
println!("Kicking my {} wheel", element.position);
}
}
fn main() {
let car = Car::new();
car.accept(&PrintVisitor {});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment