如何在Rust状态模式中实现需两次审批才能发布的逻辑?
解决Rust状态模式练习:需要两次approve才能发布文章
核心思路是利用State trait中approve方法的消费式语义(接收self: Box<Self>),通过返回新的状态实例来维护审批计数,完全不需要修改原有trait的签名。
问题分析
你之前尝试给PendingReview加计数字段,但错误地想用可变引用修改状态——但approve方法是直接拿走整个Box<Self>实例,无法获取可变引用;同时你的ready_to_approve方法里也有语法问题(直接调用add_review()没有self)。
正确实现方式
我们给PendingReview添加一个approve_count字段,每次调用approve时:
- 如果计数还没到1,返回一个计数+1的新
PendingReview实例 - 如果计数已经是1,直接返回
Published实例
完整修改后的代码如下:
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_review(&mut self) { if let Some(s) = self.state.take() { self.state = Some(s.request_review()) } } pub fn approve(&mut self) { if let Some(s) = self.state.take() { self.state = Some(s.approve()) } } } trait State { fn request_review(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_review(self: Box<Self>) -> Box<dyn State> { // 初始化审批计数为0 Box::new(PendingReview { approve_count: 0 }) } fn approve(self: Box<Self>) -> Box<dyn State> { self } } struct PendingReview { approve_count: u8, } impl State for PendingReview { fn request_review(self: Box<Self>) -> Box<dyn State> { self } fn approve(self: Box<Self>) -> Box<dyn State> { if self.approve_count == 1 { // 第二次审批,切换到发布状态 Box::new(Published {}) } else { // 第一次审批,计数+1,保持待审核状态 Box::new(PendingReview { approve_count: self.approve_count + 1, }) } } } struct Published {} impl State for Published { fn request_review(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 } }
验证逻辑
- 创建新Post:
let mut post = Post::new();→ 状态为Draft - 添加内容:
post.add_text("Hello world!"); - 请求审核:
post.request_review();→ 状态变为PendingReview(count=0) - 第一次审批:
post.approve();→ 状态变为PendingReview(count=1),此时post.content()返回空字符串 - 第二次审批:
post.approve();→ 状态变为Published,此时post.content()返回"Hello world!"
这种实现完全遵循原有代码的设计,没有破坏State trait的签名,同时完美满足了两次approve才能发布的需求。
内容的提问来源于stack exchange,提问作者paalma
相关产品推荐
相关产品推荐

