أنماط التصميم في Rust: من النظرية إلى التطبيق
أنماط التصميم هي حلول مجربة للمشكلات النمطية في تطوير البرمجيات. في Rust، بفضل نظام الملكية الفريد (ownership) وغياب البرمجة الكائنية التقليدية، تكتسب العديد من الأنماط الكلاسيكية معنى جديدًا. في هذه المقالة، سنشرح أربعة أنماط رئيسية: Singleton وFactory وBuilder وStrategy، مُكيفة مع أسلوب Rust الاصطلاحي.
1. Singleton (المنفرد) في Rust
لا توجد متغيرات ثابتة عالمية بالمعنى التقليدي في Rust. ومع ذلك، يمكن تنفيذ Singleton باستخدام lazy_static أو OnceCell. لنلقِ نظرة على مثال باستخدام std::sync::OnceLock (متاح منذ Rust 1.70).
التنفيذ باستخدام OnceLock
use std::sync::OnceLock;
static CONFIG: OnceLock<Config> = OnceLock::new();
#[derive(Debug)]struct Config { db_url: String, port: u16,}
fn get_config() -> &'static Config { CONFIG.get_or_init(|| { Config { db_url: String::from("postgres://localhost"), port: 5432, } })}
fn main() { let cfg = get_config(); println!("{:?}", cfg);}النقطة الأساسية: يضمن OnceLock التهيئة لمرة واحدة وأمان الخيوط. هذه هي الطريقة الاصطلاحية في Rust.
2. Factory (المصنع) عبر Traits
يتم تنفيذ نمط Factory في Rust بشكل ممتاز باستخدام Traits. لسنا بحاجة إلى فئات مجردة - يكفي تعريف واجهة عبر Trait.
مثال: إنشاء وسائل النقل
trait Transport { fn deliver(&self);}
struct Truck;impl Transport for Truck { fn deliver(&self) { println!("توصيل بالشاحنة عبر البر"); }}
struct Ship;impl Transport for Ship { fn deliver(&self) { println!("توصيل بالسفينة عبر البحر"); }}
struct LogisticsFactory;
impl LogisticsFactory { fn create_transport(route_type: &str) -> Box<dyn Transport> { match route_type { "land" => Box::new(Truck), "sea" => Box::new(Ship), _ => panic!("نوع مسار غير معروف"), } }}
fn main() { let transport = LogisticsFactory::create_transport("sea"); transport.deliver();}الميزة: لا يتطلب Rust الوراثة - يتم تحقيق تعدد الأشكال عبر Traits و Box<dyn Trait>.
3. Builder (الباني) بسلسلة مُنَمَّطة
يُستخدم Builder في Rust على نطاق واسع، خاصة للهياكل التي تحتوي على العديد من المعاملات الاختيارية. سنقوم بتنفيذه باستخدام سلسلة من الطرق المُنَمَّطة التي تُرجع &mut Self.
مثال: إنشاء طلب HTTP
#[derive(Debug, Default)]struct HttpRequest { url: String, method: String, headers: Vec<(String, String)>, body: Option<String>,}
struct HttpRequestBuilder { request: HttpRequest,}
impl HttpRequestBuilder { fn new(url: &str) -> Self { HttpRequestBuilder { request: HttpRequest { url: url.to_string(), method: "GET".to_string(), ..Default::default() }, } }
fn method(&mut self, method: &str) -> &mut Self { self.request.method = method.to_string(); self }
fn header(&mut self, key: &str, value: &str) -> &mut Self { self.request.headers.push((key.to_string(), value.to_string())); self }
fn body(&mut self, body: &str) -> &mut Self { self.request.body = Some(body.to_string()); self }
fn build(&self) -> HttpRequest { // يمكن إضافة التحقق هنا HttpRequest { ..self.request.clone() } }}
fn ma