Skip to content

Instantly share code, notes, and snippets.

@ilopX
Last active April 13, 2023 03:08
Show Gist options
  • Save ilopX/ce73f74a4b50de885b8a1c8b887d43bd to your computer and use it in GitHub Desktop.
Save ilopX/ce73f74a4b50de885b8a1c8b887d43bd to your computer and use it in GitHub Desktop.
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