一般例子

fn main() {
    use oop_status::Post;
 
    let mut post = Post::new();
 
    post.add_text("I ate a salad for lunch today");
    assert_eq!("",post.content());
 
    post.request_reveiw();
    assert_eq!("",post.content());
 
    post.approve();
    assert_eq!("I ate a salad for lunch today",post.content());
}
 
pub struct Post {
    state: Option<Box<dyn State>>,
    content: String,
}
 
impl Post {
    pub fn new() -> Post {
        Post {
            state: Some(Box::new(Draft {})),
            content: String::new(),
        }
    }
 
    pub fn add_text(&mut self, text: &str) {
        self.content.push_str(text);
    }
 
	/////////关键函数//////////
    pub fn content(&self) -> &str {
        self.state.as_ref().unwrap().content(&self)
    }
 
    pub fn request_reveiw(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.request_reveiw());
        }
    }
 
    pub fn approve(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.approve());
        }
    }
}
 
trait State {
    fn request_reveiw(self: Box<Self>) -> Box<dyn State>;
 
    fn approve(self: Box<Self>) -> Box<dyn State>;
 
    fn content<'a>(&self, _post: &'a Post) -> &'a str {
        ""
    }
}
 
struct Draft {}
 
impl State for Draft {
    fn request_reveiw(self: Box<Self>) -> Box<dyn State> {
        Box::new(PendingReview {})
    }
 
    fn approve(self: Box<Self>) -> Box<dyn State> {
        self
    }
}
 
struct PendingReview {}
 
impl State for PendingReview {
    fn request_reveiw(self: Box<Self>) -> Box<dyn State> {
        self
    }
 
    fn approve(self: Box<Self>) -> Box<dyn State> {
        Box::new(Published {})
    }
}
 
struct Published {}
 
impl State for Published {
    fn request_reveiw(self: Box<Self>) -> Box<dyn State> {
        self
    }
 
    fn approve(self: Box<Self>) -> Box<dyn State> {
        self
    }
 
    fn content<'a>(&self, post: &'a Post) -> &'a str {
        &post.content
    }
}
 

更加过程化的例子(利用 rust 的类型检查特性)

fn main() {
    use oop_rust_status::*;
 
    let mut post = Post::new();
 
    post.add_text("text");
 
    let post = post.request_review();
 
    let post = post.approve();
 
    assert_eq!("text",post.content());
}
pub struct Post {
    content: String,
}
 
pub struct DraftPost {
    content: String,
}
 
pub struct PendingReviewPost {
    content: String,
}
 
impl Post {
    pub fn new() -> DraftPost {
        DraftPost {
            content: String::new(),
        }
    }
 
    pub fn content(&self) -> &str {
        &self.content
    }
}
 
impl DraftPost {
    pub fn add_text(&mut self, text: &str) {
        self.content.push_str(text)
    }
 
    pub fn request_review(self) -> PendingReviewPost {
        PendingReviewPost {
            content: self.content,
        }
    }
}
 
impl PendingReviewPost {
    pub fn approve(self) -> Post {
        Post {
            content: self.content,
        }
    }
}