用 Rust 实现面向对象中的状态模式

该博客介绍了如何使用Rust实现面向对象设计模式中的状态模式,以模拟文章从草稿到发布的整个过程。文章详细展示了如何定义文章的状态(草稿、待审核、已发布)以及它们之间的转换,并通过`Post`结构体和`State` trait来实现状态的动态切换。通过这段代码,读者可以理解Rust中如何利用状态模式来管理对象的不同行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用 Rust 实现面向对象中的状态模式

使用 Rust 实现面向对象中的状态模式, 下面的代码模拟了一篇 Blog 的发布 (Post) 过程.

文章中涉及了一些 Rust 特性, 如果你是第一次接触 Rust, 可以先看这里.

准备工作

安装 Rust 环境. 看这里

新建工程, 准备 main.rslib.rs 文件.

$ cargo new blog
$ cd blog/src
$ touch lib.rc
$ ls
lib.rs  main.rs

cargo 是 Rust 的构建工具和包管理器. cargo 的入门文章看这里.

测试程序

main.rs

use blog::Post;

#[allow(unused_variables, unused_mut, unused_assignments)]
fn main() {
    // 新建一篇文章
    let mut post = Post::new();

    // 添加一些文字
    post.add_text("I ate a salad for lunch today");
    assert_eq!("", post.content()); // 文章还未发表, 看不到内容

    // 请求审核
    post.request_review();
    assert_eq!("", post.content()); // 文章还未发表, 看不到内容

    // 审核过程省略...(这里只是模拟, 真实的审核或许在其他线程进行)
    // 审核通过
    post.approve();
    assert_eq!("I ate a salad for lunch today", post.content()); // 审核通过了, 文章可以发表, 可以看到文章的内容
    
}

Post 库

lib.rs


/* 发布一篇文章经历的几个状态
 Draft: 草稿状态.    调用 request_review() 进入下一个状态
 PendingReview: 待审核状态.   调用 approve() 进入下一个状态
 Published: 已发布(审核ok)状态.   
*/

// 定义 Post 结构
#[allow(unused_variables, unused_mut, unused_assignments)]
pub struct Post {
    state: Option<Box<dyn State>>,
    content: String,
}

// Post 类型的方法
#[allow(unused_variables, unused_mut, unused_assignments)]
impl Post {

    // 创建一篇空白文章
    pub fn new() -> Self {
        Post {
            state: Some(Box::new(Draft{})), // 文章的默认状态是草稿
            content: String::new(),
        }
    }
	
	// 添加内容
    pub fn add_text(&mut self, text: &str) {
        self.content.push_str(text);
    }
	
	// 提交审核
    pub fn request_review(&mut self) {
        if let Some(local_state) = self.state.take() {
           self.state = Some(local_state.request_review());
        }
    }
	
	// 审核通过
    pub fn approve(&mut self) {
        if let Some(local_state) = self.state.take() {
            self.state = Some(local_state.approve());
         }
    }
	
	// 获取文章内容
    pub fn content(&self) -> &str {
        self.state.as_ref().unwrap().content(self)
    }
}

// 文章的三个状态应该具有的共同方法. 也就是说每个具体状态内部都要实现这个三个方法.
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 {}         // "草稿" 状态. 等待提交审核
struct PendingReview {} // "待审核" 状态.  等待审核
struct Published {}     // "已发布" 状态

// "草稿" 状态
#[allow(unused_variables, unused_mut, unused_assignments)]
impl State for Draft {

    // 提交审查后, 状态转为等待审核
    fn request_review(self: Box<Self>)  -> Box<dyn State> {
        Box::new(PendingReview{})
    }

    // 目前是草稿状态, 不能直接同意, 所以 Blog 的状态不能改变, 还是草稿
    fn approve(self: Box<Self>)  -> Box<dyn State> {
        self
    }

    // 草稿状态的 Blog 不能发表, 所以返回空串
    fn content<'a>(&self, post: &'a Post) -> &'a str {
        ""
    }
}

// "待审核" 状态
#[allow(unused_variables, unused_mut, unused_assignments)]
impl State for PendingReview {

    // blog 等待审核, 再次提交审核并不能改变 blog 的状态, 所以仍然是"待审核"状态
    fn request_review(self: Box<Self>)  -> Box<dyn State> {
        self
    }

    // 同意, 则 blog 可以发布了, 状态改为 "已发布"
    fn approve(self: Box<Self>)  -> Box<dyn State> {
        Box::new(Published{})
    }

    // blog 等待审核, 还没定稿, 不能发表, 返回空串
    fn content<'a>(&self, post: &'a Post) -> &'a str {
        ""
    }
}

// "已发布" 状态
#[allow(unused_variables, unused_mut, unused_assignments)]
impl State for Published {

    // blog 已发布, 没有请求审核的必要, 保持现有状态
    fn request_review(self: Box<Self>)  -> Box<dyn State> {
        self
    }

    // blog 已发布, 没有审核的必要, 保持现有状态
    fn approve(self: Box<Self>)  -> Box<dyn State> {
        self
    }

    // blog 已发布, 可以看到内容.
    fn content<'a>(&self, post: &'a Post) -> &'a str {
        &post.content
    }
}

原文看这里.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值