Skip to content

Commit cccf00a

Browse files
committed
state design pattern
1 parent 104f67a commit cccf00a

File tree

8 files changed

+150
-2
lines changed

8 files changed

+150
-2
lines changed

Cargo.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[workspace]
22
resolver = "3"
3-
members = ["basics","course", "guessgame", "intmut", "myutils", "paral"]
3+
members = ["basics","course", "guessgame", "intmut", "myutils", "paral", "statedesign"]

course/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ basics = { path = "../basics" }
88
myutils = { path = "../myutils" }
99
guessgame = { path = "../guessgame" }
1010
intmut = { path = "../intmut" }
11-
paral = { path = "../paral" }
11+
paral = { path = "../paral" }
12+
statedesign = { path = "../statedesign" }

course/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use myutils::testing;
55
use paral::channels;
66
use paral::mutex;
77
use paral::threads;
8+
use statedesign;
89

910
fn main() {
1011
basics::basics();
@@ -20,4 +21,6 @@ fn main() {
2021
threads::demo();
2122
channels::demo();
2223
mutex::demo();
24+
statedesign::demo();
25+
statedesign::demo2();
2326
}

statedesign/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "statedesign"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]

statedesign/src/lib.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
mod post;
2+
use post::Post;
3+
4+
pub fn demo() {
5+
println!("This is the state design pattern demo.");
6+
let mut post = Post::new();
7+
post.add_text("I ate a salad for lunch today.");
8+
assert_eq!("", post.content());
9+
post.request_review();
10+
assert_eq!("", post.content());
11+
post.approve();
12+
assert_eq!("I ate a salad for lunch today.", post.content());
13+
}
14+
15+
mod post2;
16+
17+
pub fn demo2() {
18+
println!("This is the state design pattern demo2.");
19+
let mut post = post2::Post::new();
20+
post.add_text("I ate a salad for lunch today.");
21+
let post = post.request_review();
22+
let post = post.approve();
23+
assert_eq!("I ate a salad for lunch today.", post.content());
24+
}

statedesign/src/post.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
pub struct Post {
2+
content: String,
3+
state: Option<Box<dyn State>>,
4+
}
5+
6+
impl Post {
7+
pub fn new() -> Post {
8+
Post {
9+
content: String::new(),
10+
state: Some(Box::new(Draft {})),
11+
}
12+
}
13+
pub fn add_text(&mut self, text: &str) {
14+
self.content.push_str(text);
15+
}
16+
pub fn content(&self) -> &str {
17+
self.state.as_ref().unwrap().content(self)
18+
}
19+
pub fn request_review(&mut self) {
20+
if let Some(state) = self.state.take() {
21+
self.state = Some(state.request_review());
22+
}
23+
}
24+
pub fn approve(&mut self) {
25+
if let Some(state) = self.state.take() {
26+
self.state = Some(state.approve());
27+
}
28+
}
29+
}
30+
31+
trait State {
32+
fn request_review(self: Box<Self>) -> Box<dyn State>;
33+
fn approve(self: Box<Self>) -> Box<dyn State>;
34+
fn content<'a>(&self, _post: &'a Post) -> &'a str {
35+
""
36+
}
37+
}
38+
39+
struct Draft {}
40+
41+
impl State for Draft {
42+
fn request_review(self: Box<Self>) -> Box<dyn State> {
43+
Box::new(PendingReview {})
44+
}
45+
fn approve(self: Box<Self>) -> Box<dyn State> {
46+
self
47+
}
48+
}
49+
50+
struct PendingReview {}
51+
52+
impl State for PendingReview {
53+
fn request_review(self: Box<Self>) -> Box<dyn State> {
54+
self
55+
}
56+
fn approve(self: Box<Self>) -> Box<dyn State> {
57+
Box::new(Published {})
58+
}
59+
}
60+
61+
struct Published {}
62+
63+
impl State for Published {
64+
fn request_review(self: Box<Self>) -> Box<dyn State> {
65+
self
66+
}
67+
fn approve(self: Box<Self>) -> Box<dyn State> {
68+
self
69+
}
70+
fn content<'a>(&self, post: &'a Post) -> &'a str {
71+
&post.content
72+
}
73+
}

statedesign/src/post2.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
pub struct Post {
2+
content: String,
3+
}
4+
impl Post {
5+
pub fn new() -> DraftPost {
6+
DraftPost {
7+
content: String::new(),
8+
}
9+
}
10+
pub fn content(&self) -> &str {
11+
&self.content
12+
}
13+
}
14+
pub struct DraftPost {
15+
content: String,
16+
}
17+
impl DraftPost {
18+
pub fn add_text(&mut self, text: &str) {
19+
self.content.push_str(text);
20+
}
21+
pub fn request_review(self) -> PendingReviewPost {
22+
PendingReviewPost {
23+
content: self.content,
24+
}
25+
}
26+
}
27+
pub struct PendingReviewPost {
28+
content: String,
29+
}
30+
impl PendingReviewPost {
31+
pub fn approve(self) -> Post {
32+
Post {
33+
content: self.content,
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)