searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

rust状态模式学习笔记

2025-11-11 10:32:28
0
0

Rust 状态模式(State Pattern)学习笔记

本文总结了 Rust《The Book》中关于状态模式的实现方式,并结合示例代码加以说明。

一、从 State trait 开始:定义所有状态共有的接口

整个状态模式的核心在于一个 trait:

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 {
        ""
    }
}

关键点如下:

二、三个具体状态类型

1. Draft

struct Draft {}

行为:

fn request_review(self: Box<Self>) -> Box<dyn State> {
    Box::new(PendingReview {})
}
fn approve(self: Box<Self>) -> Box<dyn State> {
    self
}

含义:

  • 草稿被“提交审核”后进入 PendingReview。
  • 草稿无法跳过审核直接“approve”,所以 approve 什么都不做。

2. PendingReview

struct PendingReview {}

行为:

fn request_review(self: Box<Self>) -> Box<dyn State> {
    self
}
fn approve(self: Box<Self>) -> Box<dyn State> {
    Box::new(Published {})
}

含义:

  • 再次 request_review 不改变状态。
  • 审核通过后进入 Published 状态。

3. Published

struct Published {}

这里Published覆盖了 content():

fn content<'a>(&self, post: &'a Post) -> &'a str {
    post.content.as_ref()
}

含义:

  • Published 是唯一能看到真正内容的状态。
  • 其他状态通过默认实现返回空字符串。

三、Post结构体:把状态作为内部字段

理解完状态类型后,才需要看 Post 的结构:

pub struct Post {
    content: String,
    state: Option<Box<dyn State>>,
}

impl Post {
    // Post的所有方法并不知道不同状态下有着不同的行为。这些都是在State这个trait中完成的
    pub fn new() -> Post {
        Post {
            content: String::new(),
            state: Some(Box::new(Draft {})),
        }
    }

    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) {
        match self.state.take() {
            Some(s) => {
                self.state = Some(s.request_review());
            },
            None => {}
        }
    }

    pub fn approve(&mut self) {
        match self.state.take() {
            Some(s) => {
                self.state = Some(s.approve());
            },
            None => {}
        }
    }
}

Post 有两部分:

  • content:存储文本内容
  • state:存储当前状态对象,哪种状态取决于 Box 内部的动态类型

注意:Post 本身不包含状态逻辑
所有状态行为由 state 字段内部的对象决定。
状态转换逻辑:

  • take() 把 state 的所有权移出
  • 调用状态对象的转换方法
  • 把新状态放回 state

四、总结

本例的状态模式有以下特点:

  1. 每种状态是独立类型
    让不同状态的行为清晰、可维护。
  2. self: Box<Self> 强制状态转换是 move 操作
    旧状态对象必然被丢弃,不会出现“状态混用”的问题。
  3. Post 本身没有写 if/else 或 match
    所有逻辑都由状态对象负责,这符合“状态模式”的核心思想。
  4. Published 覆盖 content() 实现访问控制
    利用 trait 默认实现完成简单权限控制。
陈****然
7文章数
0粉丝数
陈****然
7 文章 | 0 粉丝
陈****然
7文章数
0粉丝数
陈****然
7 文章 | 0 粉丝
原创

rust状态模式学习笔记

2025-11-11 10:32:28
0
0

Rust 状态模式(State Pattern)学习笔记

本文总结了 Rust《The Book》中关于状态模式的实现方式,并结合示例代码加以说明。

一、从 State trait 开始:定义所有状态共有的接口

整个状态模式的核心在于一个 trait:

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 {
        ""
    }
}

关键点如下:

二、三个具体状态类型

1. Draft

struct Draft {}

行为:

fn request_review(self: Box<Self>) -> Box<dyn State> {
    Box::new(PendingReview {})
}
fn approve(self: Box<Self>) -> Box<dyn State> {
    self
}

含义:

  • 草稿被“提交审核”后进入 PendingReview。
  • 草稿无法跳过审核直接“approve”,所以 approve 什么都不做。

2. PendingReview

struct PendingReview {}

行为:

fn request_review(self: Box<Self>) -> Box<dyn State> {
    self
}
fn approve(self: Box<Self>) -> Box<dyn State> {
    Box::new(Published {})
}

含义:

  • 再次 request_review 不改变状态。
  • 审核通过后进入 Published 状态。

3. Published

struct Published {}

这里Published覆盖了 content():

fn content<'a>(&self, post: &'a Post) -> &'a str {
    post.content.as_ref()
}

含义:

  • Published 是唯一能看到真正内容的状态。
  • 其他状态通过默认实现返回空字符串。

三、Post结构体:把状态作为内部字段

理解完状态类型后,才需要看 Post 的结构:

pub struct Post {
    content: String,
    state: Option<Box<dyn State>>,
}

impl Post {
    // Post的所有方法并不知道不同状态下有着不同的行为。这些都是在State这个trait中完成的
    pub fn new() -> Post {
        Post {
            content: String::new(),
            state: Some(Box::new(Draft {})),
        }
    }

    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) {
        match self.state.take() {
            Some(s) => {
                self.state = Some(s.request_review());
            },
            None => {}
        }
    }

    pub fn approve(&mut self) {
        match self.state.take() {
            Some(s) => {
                self.state = Some(s.approve());
            },
            None => {}
        }
    }
}

Post 有两部分:

  • content:存储文本内容
  • state:存储当前状态对象,哪种状态取决于 Box 内部的动态类型

注意:Post 本身不包含状态逻辑
所有状态行为由 state 字段内部的对象决定。
状态转换逻辑:

  • take() 把 state 的所有权移出
  • 调用状态对象的转换方法
  • 把新状态放回 state

四、总结

本例的状态模式有以下特点:

  1. 每种状态是独立类型
    让不同状态的行为清晰、可维护。
  2. self: Box<Self> 强制状态转换是 move 操作
    旧状态对象必然被丢弃,不会出现“状态混用”的问题。
  3. Post 本身没有写 if/else 或 match
    所有逻辑都由状态对象负责,这符合“状态模式”的核心思想。
  4. Published 覆盖 content() 实现访问控制
    利用 trait 默认实现完成简单权限控制。