I'm learning design patterns with GoFPatterns and trying to do their "Traffic Signals" exercise in Rust.
I came up with a solution:
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum SignalState {
STOP,
CAUTION,
GO,
}
trait TrafficSignal {
fn change_state(&mut self) {
match self.get_state() {
SignalState::STOP => self.set_state(SignalState::GO),
SignalState::CAUTION => self.set_state(SignalState::STOP),
SignalState::GO => {
self.passage_granted();
self.set_state(SignalState::CAUTION);
}
}
}
fn request_passage(&mut self) {
self.set_passage_requested(true);
}
fn passage_granted(&mut self) {
self.set_passage_requested(false);
}
fn set_passage_requested(&mut self, new_passage_requested: bool);
fn set_state(&mut self, new_state: SignalState);
fn get_state(&self) -> SignalState;
fn get_passage_requested(&self) -> bool;
fn get_message(&self) -> String;
}
struct TrafficLight {
passage_requested: bool,
state: SignalState,
}
impl TrafficLight {
fn new() -> Self {
Self {
passage_requested: false,
state: SignalState::STOP,
}
}
}
impl TrafficSignal for TrafficLight {
fn set_passage_requested(&mut self, new_passage_requested: bool) {
self.passage_requested = new_passage_requested;
}
fn set_state(&mut self, new_state: SignalState) {
self.state = new_state;
}
fn get_state(&self) -> SignalState {
self.state
}
fn get_passage_requested(&self) -> bool {
self.passage_requested
}
fn get_message(&self) -> String {
format!("Traffic Light : {:?}", self.state)
}
}
struct WalkSign {
passage_requested: bool,
state: SignalState,
}
impl WalkSign {
fn new() -> Self {
Self {
passage_requested: false,
state: SignalState::STOP,
}
}
}
impl TrafficSignal for WalkSign {
fn set_passage_requested(&mut self, new_passage_requested: bool) {
self.passage_requested = new_passage_requested;
}
fn set_state(&mut self, new_state: SignalState) {
self.state = new_state;
}
fn get_state(&self) -> SignalState {
self.state
}
fn get_passage_requested(&self) -> bool {
self.passage_requested
}
fn get_message(&self) -> String {
format!("Walk Sign : {:?}", self.state)
}
}
There is a lot of code duplication because in Rust we can't inherit properties, so I create setters and getters for each property to use in the TrafficSignal
trait.
How could I do it better?