模式不是套路(十一):终篇——反模式与断舍离
“模式不是目的,而是手段。当手段成为目的,代码便开始腐烂。” 走完了这趟设计模式的旅程,我们学会了用 Rust 的特性让模式返璞归真。但还有一个更重要的问题:什么时候不该用模式? 这篇终章,我们来聊聊设计模式的阴暗面——过度设计、模式滥用,以及断舍离的智慧。 过度设计的七宗罪 第一罪:未来幻想症 // ❌ 为"可能的需求"做准备 trait PaymentProcessor { fn process(&self, amount: f64) -> Result<(), Error>; fn refund(&self, transaction_id: &str) -> Result<(), Error>; fn partial_refund(&self, transaction_id: &str, amount: f64) -> Result<(), Error>; fn recurring(&self, schedule: &Schedule) -> Result<(), Error>; fn batch_process(&self, payments: Vec<Payment>) -> Result<(), Error>; fn validate_card(&self, card: &Card) -> Result<bool, Error>; fn tokenize(&self, card: &Card) -> Result<Token, Error>; fn dispute(&self, transaction_id: &str, reason: &str) -> Result<(), Error>; // 还有 20 个方法... } // ✅ 只实现当前需要的 trait PaymentProcessor { fn process(&self, amount: f64) -> Result<(), Error>; } // 需要时再扩展 trait RefundablePayment: PaymentProcessor { fn refund(&self, transaction_id: &str) -> Result<(), Error>; } 症状:接口定义了大量"将来可能用到"的方法,但实现者只用其中两三个。 Rust 的解药:trait 组合。需要什么就定义什么,通过 trait 继承和组合按需扩展。 第二罪:抽象层叠床架屋 // ❌ 抽象套抽象 trait Repository<T> { fn save(&self, entity: T) -> Result<(), Error>; } trait UserRepository: Repository<User> { fn find_by_email(&self, email: &str) -> Result<Option<User>, Error>; } trait UserRepositoryFactory { fn create(&self) -> Box<dyn UserRepository>; } trait UserRepositoryFactoryProvider { fn get_factory(&self) -> Box<dyn UserRepositoryFactory>; } // ✅ 直接了当 struct UserRepository { pool: PgPool, } impl UserRepository { pub fn save(&self, user: &User) -> Result<(), Error> { // 直接实现 } pub fn find_by_email(&self, email: &str) -> Result<Option<User>, Error> { // 直接实现 } } 症状:为了"灵活性"层层包装,但整个系统只有一种实现。 ...