1. 程式人生 > 其它 >DBA學RUST設計模式--狀態模式

DBA學RUST設計模式--狀態模式

一個物件會有不同的狀態,不同的操作會影響狀態,同時狀態改變,也會影響物件和業務流程。例如,薛定諤的貓有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介面,使上述實現成為可能。