美文网首页
rust--状态模式

rust--状态模式

作者: 极光火狐狸 | 来源:发表于2018-09-11 18:41 被阅读58次

源码: state1.rs

#[derive(Debug)]
struct StateMachine<T> {
    state: T
}


#[derive(Debug)]
struct AmState<'a> {
    name: &'a str,
    stations: Vec<&'a str>,
    pos: i32
}


#[derive(Debug)]
struct FmState<'a> {
    name: &'a str,
    stations: Vec<&'a str>,
    pos: i32
}


impl<'a> StateMachine<AmState<'a>> {
    fn new() -> Self {
        StateMachine {
            state: AmState {
                name: "AmState",
                stations: vec!["1250", "1380", "1510"],
                pos: 0
            }
        }
    }
}


impl<'a> From<StateMachine<AmState<'a>>> for StateMachine<FmState<'a>> {
    fn from(_: StateMachine<AmState>) -> StateMachine<FmState> {
        StateMachine {
            state: FmState {
                name: "FmState",
                stations: vec!["81.3", "89.1", "103.9"],
                pos: 0
            }
        }
    }
}


impl<'a> From<StateMachine<FmState<'a>>> for StateMachine<AmState<'a>> {
    fn from(_: StateMachine<FmState>) -> StateMachine<AmState> {
        StateMachine {
            state: AmState {
                name: "AmState",
                stations: vec!["1250", "1380", "1510"],
                pos: 0
            }
        }
    }
}


#[derive(Debug)]
enum StateMachineWrapper<'a> {
    AmState(StateMachine<AmState<'a>>),
    FmState(StateMachine<FmState<'a>>)
}


impl<'a> StateMachineWrapper<'a> {
    fn step(mut self) -> Self {
        self = match self {
            StateMachineWrapper::AmState(val) => StateMachineWrapper::FmState(val.into()),
            StateMachineWrapper::FmState(val) => StateMachineWrapper::AmState(val.into())
        };
        self
    }
}


// TODO: 这里只实现了AM和FM的切换, 如何便捷的实现电台的切换?
fn main() {
    let mut state = StateMachineWrapper::AmState(StateMachine::new());
    println!("state: {:?}", state);
    state = state.step();
    println!("state: {:?}", state);
}

 
 

源码: state2.rs



// 这种写法比较直, 也就是说任何环节发生变化,
// 都需要全部重新定义.

struct Post {
    content: String
}

struct DraftPost {
    content: String
}

struct PendingPost {
    content: String,
    approvals: u32

}

impl Post {
    fn new() -> DraftPost {
        DraftPost { content: String::new() }
    }

    fn content(&self) -> &str {
        &self.content
    }
}

impl DraftPost {
    fn req_review(self) -> PendingPost {
        PendingPost {
            content: self.content,
            approvals: 0
        }
    }

    fn add_text(&mut self, content: &str) {
        self.content.push_str(content);
    }
}

enum PublishResult {
    PendingPost(PendingPost),
    Post(Post)
}

impl PendingPost {
    fn approve(&mut self) {
        self.approvals += 1;
    }
    fn reject(self) -> DraftPost {
        DraftPost { content: self.content }
    }
    fn publish(self) -> PublishResult {
        if self.approvals > 1 {
            PublishResult::Post(Post{content: self.content})
        } else {
            PublishResult::PendingPost(self)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn publish_workflow() {
        let mut draft = Post::new();
        draft.add_text("ashish first post");
        let mut pending = draft.req_review();
        pending.approve();
        pending.approve();
        let publish = pending.publish();
        match publish {
            PublishResult::Post(p) => assert_eq!(p.content(),
                                                 "ashish first post"),
            _ => assert!(false)
        }
    }

    #[test]
    fn reject_workflow() {
        let mut draft = Post::new();
        draft.add_text("ashish first post");
        let pending = draft.req_review();
        let mut again_draft = pending.reject();
        again_draft.add_text(".. after first one..");
    }

    #[test]
    fn two_approvals_workflow() {
        let mut draft = Post::new();
        draft.add_text("ashish first post");
        let mut pending = draft.req_review();
        pending.approve();
        match pending.publish() {
            PublishResult::PendingPost(_) => assert!(true),
            _ => assert!(false)
        }
    }
}

 
 

源码: state3.rs



// 这种写法稍微灵活一些, 但也更复杂.
// 但仍然不够灵活.
// 参考: https://hoverbear.org/2016/10/12/rust-state-machine-pattern/

// This is our state machine.
#[derive(Debug)]
struct BottleFillingMachine<S> {
    shared_value: usize,
    state: S
}


// The following states can be the 'S' in StateMachine<S>
#[derive(Debug)]
struct Waiting {
    waiting_time: std::time::Duration,
}


#[derive(Debug)]
struct Filling {
    rate: usize,
}


#[derive(Debug)]
struct Done;


// Our Machine starts in the 'Waiting' state.
impl BottleFillingMachine<Waiting> {
    fn new(shared_value: usize) -> Self {
        BottleFillingMachine {
            shared_value: shared_value,
            state: Waiting {
                waiting_time: std::time::Duration::new(0, 0),
            }
        }
    }
}


// The following are the defined transitions between states.
impl From<BottleFillingMachine<Waiting>> for BottleFillingMachine<Filling> {
    fn from(val: BottleFillingMachine<Waiting>) -> BottleFillingMachine<Filling> {
        BottleFillingMachine {
            shared_value: val.shared_value,
            state: Filling {
                rate: 1,
            }
        }
    }
}

impl From<BottleFillingMachine<Filling>> for BottleFillingMachine<Done> {
    fn from(val: BottleFillingMachine<Filling>) -> BottleFillingMachine<Done> {
        BottleFillingMachine {
            shared_value: val.shared_value,
            state: Done,
        }
    }
}


impl From<BottleFillingMachine<Done>> for BottleFillingMachine<Waiting> {
    fn from(val: BottleFillingMachine<Done>) -> BottleFillingMachine<Waiting> {
        BottleFillingMachine {
            shared_value: val.shared_value,
            state: Waiting {
                waiting_time: std::time::Duration::new(0, 0),
            }
        }
    }
}


// Here is we're building an enum so we can contain this state machine in a parent.
#[derive(Debug)]
enum BottleFillingMachineWrapper {
    Waiting(BottleFillingMachine<Waiting>),
    Filling(BottleFillingMachine<Filling>),
    Done(BottleFillingMachine<Done>),
}


// 这里使用的是mut self, 表示它是一个实例化对象.
// 实例化对象证明enum BottleFillingMachineWrapper的成员存在有效对象.
// 因此BottleFillingMachineWrapper::Waiting(val) 中的 val 是一个结构体.
// 又由于val这个具体是一个struct且实现了From trait, 因此使用val.into会得到这个具体值.
// 最终将enum的某个状态转移到另外一个状态并且保证值的一致性.
// 总结: 这个就是状态机核心流转机制.
impl BottleFillingMachineWrapper {
    fn step(mut self) -> Self {
        self = match self {
            BottleFillingMachineWrapper::Waiting(val) => BottleFillingMachineWrapper::Filling(val.into()),
            BottleFillingMachineWrapper::Filling(val) => BottleFillingMachineWrapper::Done(val.into()),
            BottleFillingMachineWrapper::Done(val) => BottleFillingMachineWrapper::Waiting(val.into()),
        };
        self
    }
}


// The structure with a parent.
// 工厂模式: 帮你初始化和实例化状态机枚举对象: BottleFillingMachineWrapper::Wait(x)
//           帮你初始化和实例化状态机对象: BottleFillingMachine::new(0)
#[derive(Debug)]
struct Factory {
    bottle_filling_machine: BottleFillingMachineWrapper,
}


impl Factory {
    fn new() -> Self {
        Factory {
            bottle_filling_machine: BottleFillingMachineWrapper::Waiting(BottleFillingMachine::new(0)),
        }
    }
}


// 使用工厂模式作为开端, 然后运行step() 获得一个状态.
fn main() {
    // 得到Waiting状态
    let mut the_factory = Factory::new();
    println!("the_factory.bottle_filling_machine.step(): {:?}", the_factory);

    // 得到Filling状态
    the_factory.bottle_filling_machine = the_factory.bottle_filling_machine.step();
    println!("the_factory.bottle_filling_machine.step(): {:?}", the_factory);

    // 得到Done状态
    the_factory.bottle_filling_machine = the_factory.bottle_filling_machine.step();
    println!("the_factory.bottle_filling_machine.step(): {:?}", the_factory);

    // 得到Waiting状态
    the_factory.bottle_filling_machine = the_factory.bottle_filling_machine.step();
    println!("the_factory.bottle_filling_machine.step(): {:?}", the_factory);
}

相关文章

  • rust--状态模式

    源码: state1.rs 源码: state2.rs 源码: state3.rs

  • rust--建造者模式

  • State模式

    状态模式(State模式) 定义 状态模式,又称状态对象模式(Pattern of Objects for S...

  • 设计模式-状态模式

    设计模式-状态模式 设计模式 状态模式的关键是区分事物内部的状态

  • rust--宏

  • 状态模式(状态机模式)

    状态模式学习笔记 前言:文章从三方面简单阐述状态模式:是什么、为什么、如何做。这是我在工作之余自己的一些理解、思考...

  • C++设计模式(3)

    本文预览: 状态模式 组合模式 迭代器 职责链 命令 状态模式 定义:状态模式(State Pattern),允许...

  • 设计模式——状态模式

    定义 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行...

  • 第5章 -行为型模式-状态模式

    一、状态模式的简介 二、状态模式的优缺点 三、状态模式的实例

  • 状态模式

    Android进阶之设计模式 状态模式 定义: 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了...

网友评论

      本文标题:rust--状态模式

      本文链接:https://www.haomeiwen.com/subject/oktpgftx.html