library/
state_pattern.rs

1mod states;
2
3struct Post {
4    state: Option<Box<dyn states::State>>,
5    content: String,
6}
7
8impl Post {
9    pub fn new() -> Post {
10        Post {
11            state: Some(Box::new(states::Draft {})),
12            content: String::new(),
13        }
14    }
15    pub fn add_text(&mut self, msg: &str) {
16        self.content.push_str(msg);
17    }
18    pub fn request_review(&mut self) {
19        self.state = Some(self.state.take().unwrap().request_review());
20    }
21    pub fn approve(&mut self) {
22        self.state = Some(self.state.take().unwrap().approve());
23    }
24    pub fn content(&self) -> &str {
25        self.state.as_ref().unwrap().content(self)
26    }
27}
28
29#[cfg(test)]
30mod test {
31    use super::*;
32
33    #[test]
34    fn post() {
35        let mut post = Post::new();
36        assert_eq!("", post.content());
37
38        post.approve();
39        assert_eq!("", post.content());
40
41        post.add_text("hello world");
42        assert_eq!("", post.content());
43
44        post.request_review();
45        assert_eq!("", post.content());
46
47        post.approve();
48        assert_eq!("hello world", post.content());
49
50        post.request_review();
51        assert_eq!("hello world", post.content());
52    }
53}