You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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,返回一个计数+1的新PendingReview实例
  2. 如果计数已经是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
    }
}

验证逻辑

  1. 创建新Post:let mut post = Post::new(); → 状态为Draft
  2. 添加内容:post.add_text("Hello world!");
  3. 请求审核:post.request_review(); → 状态变为PendingReview(count=0)
  4. 第一次审批:post.approve(); → 状态变为PendingReview(count=1),此时post.content()返回空字符串
  5. 第二次审批:post.approve(); → 状态变为Published,此时post.content()返回"Hello world!"

这种实现完全遵循原有代码的设计,没有破坏State trait的签名,同时完美满足了两次approve才能发布的需求。

内容的提问来源于stack exchange,提问作者paalma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 07:25:53