DBA學RUST設計模式--狀態模式
阿新 • • 發佈:2021-06-26
一個物件會有不同的狀態,不同的操作會影響狀態,同時狀態改變,也會影響物件和業務流程。例如,薛定諤的貓有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介面,使上述實現成為可能。