3

Rust语言之GoF设计模式:状态模式

 1 year ago
source link: https://www.jdon.com/62621
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Rust语言之GoF设计模式:状态模式

状态模式与有限状态机 (FSM) 概念相关,但是,每个状态都由实现公共状态特征的单独类型表示,而不是实现大量条件语句。
状态之间的转换取决于每种状态类型的特定 trait 实现。
Rust 中的状态模式在Rust Book中有详细描述: https://doc.rust-lang.org/book/ch17-03-oo-design-patterns.html

状态模式经常与命令模式 混合使用,因为一个命令执行以后,必然带来状态的改变,命令促使状态变化,状态变化也可以使用事件活动表达,一个命令下达被执行以后,发出领域事件 ,这是事件溯源 的原理,事件溯源是一种 备忘录模式,通过备忘录可以实现时光旅行,返回历史上任何一个状态。

状态模式有一个基本 trait State和方法可以进行状态转换play:stop
pub trait State {
    fn play(self: Box<Self>, player: &mut Player) -> Box<dyn State>;
    fn stop(self: Box<Self>, player: &mut Player) -> Box<dyn State>;
}
next并且prev不更改状态,在impl dyn State中无法覆盖的单独块中可默认实现:
impl dyn State {
    pub fn next(self: Box<Self>, player: &mut Player) -> Box<dyn State> {
        self
    }

    pub fn prev(self: Box<Self>, player: &mut Player) -> Box<dyn State> {
        self
    }
}
每个状态都是实现的类型trait State:
pub struct StoppedState;
pub struct PausedState;
pub struct PlayingState;

impl State for StoppedState {
    ...
}

impl State for PausedState {
    ...
}
在这些实现状态再完成play动作,如PlayingState代码:
fn play(self: Box<Self>, player: &mut Player) -> Box<dyn State> {
    player.pause();

    // Playing -> Paused.
    Box::new(PausedState)
}
这里用特殊self: Box<Self>符号定义。
  • 首先,self不是一个引用,这意味着该方法是一种 "一次性的",它消耗了self并交换到另一个返回Box<dyn State>的状态。
  • 其次,该方法消耗的是Box<dyn State>这样的Box对象,而不是像PlayingState这样的具体类型的对象,因为具体状态在编译时是未知的。
最后,调用相同的操作play会根据调用的位置转换到不同的状态:
let state = Box::new(StoppedState);   // StoppedState.
let state = state.play(&mut player);  // StoppedState -> PlayingState.
let state = state.play(&mut player);  // PlayingState -> PausedState.

什么是Rust语言的类型状态Typestate模式?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK