Last active
April 13, 2023 03:08
-
-
Save ilopX/ce73f74a4b50de885b8a1c8b887d43bd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::mem; | |
fn main() { | |
let mut person = Person::new(); | |
person_test(&mut person); | |
let mut person_st = PersonSt::new(); | |
person_test(&mut person_st); | |
} | |
///------------------------------------------------------------------------------------------------- | |
fn person_test(person: &mut impl IPerson) { | |
assert_eq!(person.name(), "none"); | |
person.click(11, 1); | |
assert_eq!(person.name(), "two"); | |
person.click(21, 0); | |
assert_eq!(person.name(), "three"); | |
} | |
trait IPerson { | |
fn name(&self) -> String; | |
fn click(&mut self, x: i32, y: i32); | |
} | |
///------------------------------------------------------------------------------------------------- | |
struct Person<'a> { | |
state: Box<dyn State + 'a>, | |
} | |
impl<'a> Person<'a> { | |
fn new() -> Self { | |
Self { | |
state: Box::new(NoneState {}), | |
} | |
} | |
fn set_state(&mut self, state: impl State + 'a) { | |
self.state = Box::new(state); | |
} | |
fn detach_state(&mut self) -> Box<dyn State + 'a> { | |
mem::replace( | |
&mut self.state, | |
Box::new(NoneState), | |
) | |
} | |
} | |
impl<'a> IPerson for Person<'a> { | |
fn name(&self) -> String { | |
self.state.name() | |
} | |
fn click(&mut self, x: i32, y: i32) { | |
self.detach_state().click(self, x, y); | |
} | |
} | |
trait State { | |
fn click(&self, person: &mut Person, x: i32, y: i32); | |
fn name(&self) -> String; | |
} | |
struct NoneState; | |
impl State for NoneState { | |
fn click(&self, person: &mut Person, x: i32, y: i32) { | |
if x > 10 && y < 5 { | |
person.set_state(TwoState {}); | |
} | |
} | |
fn name(&self) -> String { | |
String::from("none") | |
} | |
} | |
struct TwoState; | |
impl State for TwoState { | |
fn click(&self, person: &mut Person, x: i32, _: i32) { | |
if x > 20 { | |
person.set_state(ThreeState) | |
} | |
} | |
fn name(&self) -> String { | |
String::from("two") | |
} | |
} | |
struct ThreeState; | |
impl State for ThreeState { | |
fn click(&self, person: &mut Person, _: i32, _: i32) { | |
person.set_state(NoneState); | |
} | |
fn name(&self) -> String { | |
String::from("three") | |
} | |
} | |
///------------------------------------------------------------------------------------------------- | |
struct PersonSt { | |
state: StateSt, | |
} | |
impl PersonSt { | |
fn new() -> Self { | |
Self { | |
state: StateSt::None, | |
} | |
} | |
} | |
impl IPerson for PersonSt { | |
fn name(&self) -> String { | |
match self.state { | |
StateSt::None => "none", | |
StateSt::Two => "two", | |
StateSt::Three => "three", | |
}.to_string() | |
} | |
fn click(&mut self, x: i32, y: i32) { | |
let state = mem::replace(&mut self.state, StateSt::None); | |
state.click(self, x, y); | |
} | |
} | |
enum StateSt { | |
None, | |
Two, | |
Three, | |
} | |
impl StateSt { | |
fn click(&self, person: &mut PersonSt, x: i32, y: i32) { | |
match self { | |
StateSt::None => { | |
if x > 10 && y < 5 { | |
person.state = StateSt::Two; | |
} | |
} | |
StateSt::Two => { | |
if x > 20 { | |
person.state = StateSt::Three; | |
} | |
} | |
StateSt::Three => { | |
person.state = StateSt::None; | |
} | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment