标签:业务流程 需要 数据 描述 规则 假设 获取 转换 dead
一个对象会有不同的状态,不同的操作会影响状态,同时状态改变,也会影响对象和业务流程。例如,薛定谔的猫有3种状态:生、死、不确定,假设3种状态可转换.
名称为CatState的trait描述了对猫的所有状态操作:
trait CatState { fn make_live(self: Box<Self>) -> Box<dyn CatState>; //使猫生 fn make_dead(self: Box<Self>) -> Box<dyn CatState>; //使猫死 fn make_uncertain(self: Box<Self>) -> Box<dyn CatState>; //使猫变得不确定 }
接下来,定义一个结构体猫,该结构体包含一个属性:state。结构体描述了猫的状态信息,由于状态数据长度的不确定性和,因此使用存储在堆上的Box包裹trait方式定义。任何想要获取或者设置state值,都要实现CatState这个trait。
struct Cat{ state: Option<Box<dyn CatState>>, } //Cat实现类,前台调用,因此使用mut传递前端参数,获取可变引用。 impl Cat { fn make_live_impl(&mut self) { if let Some(s) = self.state.take() { //此处的s也即self,为前端实例化后的对象,该对象需实现trait:CatState self.state = Some(s.make_live()) } } fn make_dead_impl(&mut self) { if let Some(s) = self.state.take() { self.state = Some(s.make_dead()) } } fn make_uncertain_impl(&mut self) { if let Some(s) = self.state.take() { self.state = Some(s.make_uncertain()) } } }
接下来,需要实现具体状态的转换规则,具体规则需根据业务逻辑自行设定这里设置了3种状态,分别为live_state、dead_state、uncertain_state,每种状态下分别实现了trait接口全部功能,包含了相应的转换处理规则。这里的规则是,live -> dead -> uncertain -> live
这里使用了Box<Self>,获取所有权,防止实例化后的struct有多个状态。
struct live_state {} struct dead_state {} struct uncertain_state {} impl CatState for live_state { fn make_live(self: Box<Self>) -> Box<dyn CatState> { println!("本来就是活的!"); self } fn make_dead(self: Box<Self>) -> Box<dyn CatState> { println!("已使猫死亡!"); Box::new(dead_state {}) //有了这里,就省去了前台的if语句 } fn make_uncertain(self: Box<Self>) -> Box<dyn CatState> { println!("live状态不可转uncertain"); self } }
同理实现其余状态
impl CatState for dead_state { fn make_live(self: Box<Self>) -> Box<dyn CatState> { println!("已经死亡,无法复活"); self } fn make_dead(self: Box<Self>) -> Box<dyn CatState> { println!("本来就是死的!"); self } fn make_uncertain(self: Box<Self>) -> Box<dyn CatState> { println!("成功设置为uncertain!"); Box::new(uncertain_state {}) } } impl CatState for uncertain_state { fn make_live(self: Box<Self>) -> Box<dyn CatState> { println!("成功复活"); Box::new(live_state {}) } fn make_dead(self: Box<Self>) -> Box<dyn CatState> { println!("无法从uncertain转dead"); self } fn make_uncertain(self: Box<Self>) -> Box<dyn CatState> { println!("本来就是uncertain"); self } }
前台调用
let mut special_cat = Cat{state:Some(Box::new(dead_state{}))}; special_cat.make_live_impl(); special_cat.make_uncertain_impl();
总结
状态模型主要是要抽象出影响状态的行为和对应的状态值,一般是1对1对应关系。应依据状态行为编写trait接口,有多少行为就编写多少接口。
前端初始化运行,通过调取不同的函数,在实现类内部改变Cat的状态。由于cat的实现类和实例化类都实现了CatState接口,使上述实现成为可能。
标签:业务流程 需要 数据 描述 规则 假设 获取 转换 dead
原文地址:https://www.cnblogs.com/ggcfpe/p/14934538.html