趣味学RUST基础篇(OOP)
章鱼小新的火锅帝国越做越大,有一天,他遇到了三位程序员大佬:
- Java先生:穿着西装,一丝不苟
- Python小姐:优雅知性,随性自然
- Rust博士:戴着墨镜,酷酷的
他们都在争论一个问题:“到底什么是最好的编程方式?”
故事开始:三种不同的开店哲学
1. Java先生的"标准连锁店"模式
// 每家店都必须严格遵守总部规定
public class HotPotStore extends Restaurant {private String location;private int seats;public void serveFood() {// 必须按照标准流程System.out.println("标准上菜流程开始...");}
}
就像麦当劳:
- 所有店装修一模一样
- 所有员工动作标准化
- 严格按照手册操作
2. Python小姐的"自由创意店"模式
# 每家店都可以自由发挥
class HotPotStore:def __init__(self, location):self.location = locationdef serve_food(self):print(f"{self.location}特色上菜!")
就像网红餐厅:
- 每家店都有独特风格
- 员工可以自由发挥
- 创意无限
3. Rust博士的"智能模块店"模式
// 不是继承,而是组合!
struct HotPotStore {location: String,service: Box<dyn Service>,kitchen: Box<dyn Kitchen>,
}impl HotPotStore {fn serve_food(&self) {self.service.welcome();self.kitchen.cook();}
}
就像智能餐厅:
- 核心是模块化
- 可以自由组合
- 安全又高效
什么是面向对象编程(OOP)?
简单说,就是把程序当成一个真实世界来设计!就像开火锅店:
- 对象 = 店铺、员工、顾客、锅底
- 属性 = 店铺位置、员工姓名、顾客口味
- 方法 = 上菜、加汤、结账
OOP的三大核心特性
1. 封装(Encapsulation)—— 保护商业机密
struct SecretRecipe {// 外人看不到配方secret_ingredient: String, spice_level: u32,
}impl SecretRecipe {// 只能通过官方渠道使用pub fn cook(&self) {println!("使用秘制配方...");}
}
就像:
- 你的秘制锅底配方锁在保险箱
- 员工只能按按钮做菜,不知道配方
2. 继承(Inheritance)—— 连锁店模式(统一模板)
// 普通店
class NormalStore extends HotPotStore { }// VIP店
class VipStore extends HotPotStore { // 可以加特殊服务void servePremium() { }
}
问题来了:
- 如果要开"外卖专营店",但不需要堂食功能怎么办?
- 继承太多层,就像俄罗斯套娃,越来越复杂!
3. 多态(Polymorphism)—— 一店多能
trait StoreService {fn serve(&self);
}struct NormalStore;
struct VipStore;impl StoreService for NormalStore {fn serve(&self) {println!("标准服务");}
}impl StoreService for VipStore {fn serve(&self) {println!("VIP专属服务");}
}// 同一个函数,不同表现
fn manage_store<T: StoreService>(store: T) {store.serve(); // 自动选择对应服务
}
就像:
- 同一个管理系统
- 可以管理普通店和VIP店
- 自动适配不同服务标准
Rust的"取舍之道"
章鱼小新发现:每种方式都有优缺点!
模式 | 优点 | 缺点 |
---|---|---|
Java式继承 | 标准化,易管理 | 灵活性差,扩展难 |
Python式自由 | 灵活,创意多 | 容易出错,难维护 |
Rust式组合 | 安全,灵活,高效 | 学习成本高 |
章鱼小新的经营智慧
“没有最好的模式,只有最适合的模式!”
他总结了三条黄金法则:
- 需要标准化 → 用类似OOP的模式
- 需要灵活性 → 用Rust的Trait系统
- 需要安全性 → 用Rust的所有权机制
实际应用
1. 开设新分店
// 不用继承,用组合
let beijing_store = HotPotStore {location: "北京".to_string(),service: Box::new(ModernService),kitchen: Box::new(NorthernKitchen),
};let shanghai_store = HotPotStore {location: "上海".to_string(),service: Box::new(ElegantService),kitchen: Box::new(SouthernKitchen),
};
2. 升级服务
// 可以随时更换服务模块
beijing_store.service = Box::new(VipService);
// 立刻升级为VIP服务!
编程就像开餐厅:
- OOP 是一种思维方式,不是具体语法
- Rust 选择了更安全、更灵活的实现方式
- 关键是解决问题,而不是拘泥于某种"主义"
章鱼小新最后说:
“我的火锅帝国之所以成功,不是因为用了某种’高级’的编程方式,而是因为始终以顾客体验为中心,灵活运用各种工具!”
记住:编程没有绝对的对错,只有是否适合当前场景!
章鱼小新火锅帝国的"万能服务员"系统!
章鱼小新的火锅帝国遇到了一个大难题:每家分店的服务标准不统一!
北京店的服务员会讲相声,上海店的会说沪语,成都店的会变脸…怎么让总部系统能统一管理所有特色服务员呢?
问题:服务员类型太多了!
// 每种服务员都是不同类型
struct BeijingWaiter;
struct ShanghaiWaiter;
struct ChengduWaiter;// 它们都有自己的服务方式
impl BeijingWaiter {fn serve_with_xiangsheng(&self) {println!("来咯~ 火锅到啦!");}
}impl ShanghaiWaiter {fn serve_with_shanghainese(&self) {println!("阿拉来哉,火锅好啦!");}
}impl ChengduWaiter {fn serve_with_bianlian(&self) {println!("变脸!上菜!");}
}
总部系统傻眼了:这么多不同类型的服务员,怎么统一管理?
解决方案:Trait对象(万能服务员接口)
章鱼小新灵机一动:为什么不定义一个"标准服务接口"呢?
// 定义所有服务员都必须遵守的标准
trait WaiterService {fn welcome(&self);fn serve_food(&self);fn clean_table(&self);
}// 让每种服务员都实现这个标准
impl WaiterService for BeijingWaiter {fn welcome(&self) {println!("各位老铁,欢迎来到京城火锅!");}fn serve_food(&self) {self.serve_with_xiangsheng(); // 调用特色服务}fn clean_table(&self) {println!("给您擦个桌子,顺带讲个段子~");}
}impl WaiterService for ShanghaiWaiter {fn welcome(&self) {println!("欢迎侬来吃火锅!");}fn serve_food(&self) {self.serve_with_shanghainese();}fn clean_table(&self) {println!("阿拉帮侬擦台子~");}
}impl WaiterService for ChengduWaiter {fn welcome(&self) {println("欢迎来耍!");}fn serve_food(&self) {self.serve_with_bianlian();}fn clean_table(&self) {println("变个脸,顺便擦个桌子!");}
}
万能服务员系统上线!
现在,总部可以用统一的方式管理所有服务员了:
// 创建一个"万能服务员"列表
let mut all_waiters: Vec<Box<dyn WaiterService>> = Vec::new();// 添加各种特色服务员
all_waiters.push(Box::new(BeijingWaiter));
all_waiters.push(Box::new(ShanghaiWaiter));
all_waiters.push(Box::new(ChengduWaiter));// 统一管理!
for waiter in &all_waiters {waiter.welcome();waiter.serve_food();waiter.clean_table();
}
Trait对象的三大神奇之处
1. 类型擦除:忘记具体类型
- 总部系统不再关心"这是北京服务员还是上海服务员"
- 只知道"这是一个会服务的服务员"
2. 动态分发:自动选择正确方法
// 运行时自动决定:
// - 遇到北京服务员,就用相声方式服务
// - 遇到上海服务员,就用沪语方式服务
waiter.serve_food();
3. 统一接口:一个系统管所有
// 培训系统
fn train_waiter(waiter: &dyn WaiterService) {waiter.welcome();waiter.serve_food();// 所有服务员都能用同一个培训系统
}// 质检系统
fn check_service(waiter: &dyn WaiterService) -> bool {// 检查服务标准是否达标true
}
实际应用场景
1. 智能调度系统
struct DispatchSystem {available_waiters: Vec<Box<dyn WaiterService>>,
}impl DispatchSystem {fn assign_table(&mut self, table_id: u32) {if let Some(waiter) = self.available_waiters.pop() {// 无论是什么类型的服务员// 都能完成服务任务tokio::spawn(async move {waiter.welcome().await;waiter.serve_food().await;});}}
}
2. 服务评价系统
fn collect_feedback(waiter: &dyn WaiterService) -> Feedback {// 收集顾客对服务的评价// 无论服务员来自哪里get_customer_rating()
}
3. 自动化培训
async fn online_training(waiter: Box<dyn WaiterService>) {// 所有服务员参加同一套在线培训learn_new_service_skills(waiter).await;
}
注意事项:性能小代价
虽然好用,但也有一个小缺点:
- 静态分发(编译时决定):像直接打电话,最快
- 动态分发(运行时决定):像通过总机转接,稍微慢一点
但在大多数情况下,这点性能损失完全可以接受!
为什么叫"对象"?
因为 Box<dyn WaiterService>
就像一个"服务对象":
- 包含了数据(服务员的状态)
- 包含了方法(服务技能)
- 通过指针访问(就像服务员的工牌)
“一个好的连锁品牌,不应该要求所有员工都一模一样,而应该建立统一的服务标准,让每个员工都能发挥自己的特色!”
章鱼小新火锅店的"智能状态机"大升级!
章鱼小新的火锅帝国又遇到了新问题:**顾客点的菜品状态混乱!**有的顾客刚下单就说"上菜",有的吃完不给钱就想走…这可不行!必须建立一套智能的状态管理系统。
问题:订单状态太混乱
// 老系统:用字符串记录状态
enum OrderStatus {Draft, // 草稿 - 刚点单PendingReview, // 待审核 - 厨房确认Published, // 已发布 - 可以上菜
}struct Order {status: OrderStatus,items: Vec<String>,
}
老系统的问题:
- 服务员可能在"草稿"状态就上菜
- 厨房可能在"待审核"状态就开火
- 容易出错,没有强制约束
解决方案:状态模式(State Pattern)
章鱼小新决定引入"智能状态机"系统!
1. 定义状态接口
trait OrderState {fn add_item(&self, order: &mut Order, item: String);fn submit(&self, order: &mut Order);fn approve(&self, order: &mut Order);fn serve(&self, order: &mut Order);fn pay(&self, order: &mut Order);
}
2. 实现各种状态
草稿状态(Draft)
struct Draft;impl OrderState for Draft {fn add_item(&self, order: &mut Order, item: String) {order.items.push(item); // 可以加菜}fn submit(&self, order: &mut Order) {// 提交审核,进入待审核状态order.state = Some(Box::new(PendingReview));}fn approve(&self, _order: &mut Order) {// 草稿状态不能直接批准!println!("请先提交订单!");}fn serve(&self, _order: &mut Order) {println!("订单还没提交,不能上菜!");}fn pay(&self, _order: &mut Order) {println!("还没上菜呢,付什么钱!");}
}
待审核状态(PendingReview)
struct PendingReview;impl OrderState for PendingReview {fn add_item(&self, _order: &mut Order, _item: String) {println!("订单已提交,不能再加菜!");}fn submit(&self, _order: &mut Order) {println!("已经提交过了!");}fn approve(&self, order: &mut Order) {// 审核通过,可以上菜了!order.state = Some(Box::new(Published));}fn serve(&self, _order: &mut Order) {println!("请先审核通过!");}fn pay(&self, _order: &mut Order) {println!("菜还没上呢!");}
}
已发布状态(Published)
struct Published;impl OrderState for Published {fn add_item(&self, _order: &mut Order, _item: String) {println!("用餐中,不能加菜!");}fn submit(&self, _order: &mut Order) {println!("订单已完成!");}fn approve(&self, _order: &mut Order) {println!("已经通过审核了!");}fn serve(&self, _order: &mut Order) {println!("上菜啦!请慢用~");}fn pay(&self, _order: &mut Order) {println!("谢谢惠顾!欢迎下次光临!");// 自动进入完成状态...}
}
智能订单系统
struct Order {state: Option<Box<dyn OrderState>>,items: Vec<String>,
}impl Order {fn new() -> Order {Order {state: Some(Box::new(Draft)),items: Vec::new(),}}fn add_item(&mut self, item: String) {if let Some(state) = &self.state {state.add_item(self, item);}}fn submit(&mut self) {if let Some(state) = self.state.take() {state.submit(self);}}fn approve(&mut self) {if let Some(state) = self.state.take() {state.approve(self);}}fn serve(&mut self) {if let Some(state) = &self.state {state.serve(self);}}fn pay(&mut self) {if let Some(state) = self.state.take() {state.pay(self);}}
}
实际使用场景
let mut order = Order::new();// 1. 点菜
order.add_item("麻辣牛肉".to_string());
order.add_item("鲜毛肚".to_string());// 2. 提交订单
order.submit(); // 进入待审核状态// 3. 厨房审核
order.approve(); // 审核通过,可以上菜// 4. 上菜
order.serve(); // "上菜啦!请慢用~"// 5. 用餐结束
order.pay(); // "谢谢惠顾!欢迎下次光临!"
状态模式的三大好处
1. 防止非法操作
- 不能在草稿状态就上菜
- 不能在待审核状态加菜
- 每个状态只能做合法的事
2. 易于扩展
想加个"外卖中"状态?
struct Delivering;
impl OrderState for Delivering {fn add_item(&self, _order: &mut Order, _item: String) {println!("外卖途中,不能加菜!");}// ...其他方法
}
只需新增一个状态类,不用修改现有代码!
3. 业务逻辑清晰
每个状态的职责分明:
Draft
:负责点菜PendingReview
:负责审核Published
:负责服务和收款
章鱼小新的经营智慧
“一个好的管理系统,不应该靠员工自觉遵守流程,而应该让系统本身就能防止错误发生!”
他总结了状态模式的适用场景:
- 有明确的状态流转:草稿 → 审核 → 发布 → 完成
- 不同状态有不同的行为:草稿能编辑,发布后只能查看
- 需要防止非法操作:不能跳过审核直接上菜
两种实现方式
方式一:传统OOP风格
- 状态转换由Order控制
- 需要手动管理状态转移
方式二:Rust风格
fn submit(&mut self) {if let Some(state) = self.state.take() {self.state = Some(state.submit());}
}
- 状态自己决定下一步是什么
- 更安全,不会出现中间状态
总结
状态模式就像:
- 地铁闸机:没刷卡进不去,出站要刷卡
- 电梯按钮:只能按当前楼层允许的按钮
- 游戏关卡:必须通关才能进入下一关
记住:当你有一系列状态,且不同状态有不同的行为时,状态模式就是你的最佳选择!