DBA学RUST设计模式--状态模式

时间:2021-06-28 18:49:22   收藏:0   阅读:0

一个对象会有不同的状态,不同的操作会影响状态,同时状态改变,也会影响对象和业务流程。例如,薛定谔的猫有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接口,使上述实现成为可能。

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!