أنماط التصميم المتقدمة في Rust مع أمثلة الكود

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

أنماط التصميم في Rust: المستوى المتقدم مع أمثلة

\n\n

أنماط التصميم هي حلول مجربة للمشكلات النمطية تساعد في إنشاء بنية مرنة وقابلة للصيانة والتوسع. في Rust، مع نظام الملكية والاقتراض والسمات، تكتسب العديد من الأنماط الكلاسيكية تنفيذاً فريداً. في هذه المقالة، سنحلل أنماط التصميم المتقدمة التي تكون فعالة بشكل خاص في نظام Rust البيئي.

\n\n

1. نمط Builder المتقدم (البناء)

\n\n

غالباً ما يتم تنفيذ نمط Builder الكلاسيكي في Rust من خلال سلسلة من الدوال التي تعيد &mut Self. ومع ذلك، على المستوى المتقدم، نستخدم Builder المُنمّط مع أنواع الحالات لضمان الصحة في مرحلة التجميع.

\n\n

المشكلة: التحكم في الحقول الإلزامية

\n

لا يضمن Builder العادي أن المستخدم قد ملأ جميع الحقول الإلزامية. قد ننسى استدعاء .build() أو عدم تعيين معلمة بالغة الأهمية.

\n\n

الحل: Builder مع أنواع وهمية

\n
use std::marker::PhantomData;\n\n// أنواع الحالات للحقول\nstruct UsernameNotSet;\nstruct UsernameSet;\nstruct PasswordNotSet;\nstruct PasswordSet;\n\nstruct UserBuilder<U, P> {\n    username: Option<String>,\n    password: Option<String>,\n    _username: PhantomData<U>,\n    _password: PhantomData<P>,\n}\n\nimpl UserBuilder<UsernameNotSet, PasswordNotSet> {\n    pub fn new() -> Self {\n        Self {\n            username: None,\n            password: None,\n            _username: PhantomData,\n            _password: PhantomData,\n        }\n    }\n}\n\nimpl<P> UserBuilder<UsernameNotSet, P> {\n    pub fn username(mut self, name: &str) -> UserBuilder<UsernameSet, P> {\n        self.username = Some(name.to_string());\n        UserBuilder {\n            username: self.username,\n            password: self.password,\n            _username: PhantomData,\n            _password: PhantomData,\n        }\n    }\n}\n\nimpl<U> UserBuilder<U, PasswordNotSet> {\n    pub fn password(mut self, pwd: &str) -> UserBuilder<U, PasswordSet> {\n        self.password = Some(pwd.to_string());\n        UserBuilder {\n            username: self.username,\n            password: self.password,\n            _username: PhantomData,\n            _password: PhantomData,\n        }\n    }\n}\n\nimpl UserBuilder<UsernameSet, PasswordSet> {\n    pub fn build(self) -> User {\n        User {\n            username: self.username.expect("Username must be set"),\n            password: self.password.expect("Password must be set"),\n        }\n    }\n}\n\npub struct User {\n    pub username: String,\n    pub password: String,\n}\n\nfn main() {\n    // الآن لن يسمح المترجم باستدعاء build() دون تعيين كلا الحقلين\n    let user = UserBuilder::new()\n        .username("alice")\n        .password("secret123")\n        .build();\n    println!("User: {}", user.username);\n}
\n\n

الميزة: يتم اكتشاف خطأ "نسيان الحقل" في مرحلة التجميع، وليس في وقت التشغيل.

\n\n

2. نمط State (الحالة) عبر السمات

\n\n

يسمح نمط State للكائن بتغيير سلوكه عند تغيير حالته الداخلية. في Rust، يتم تنفيذ ذلك بأناقة عبر التعدادات (enum) والسمات.

\n\n

التنفيذ باستخدام enum

\n
enum ConnectionState {\n    Disconnected,\n    Connecting,\n    Connected,\n}\n\nstruct Connection {\n    state: ConnectionState,\n}\n\nimpl Connection {\n    pub fn new() -> Self {\n        Self { state: ConnectionState::Disconnected }\n    }\n\n    pub fn connect(&mut self) {\n        match self.state {\n            ConnectionState::Disconnected => {\n                println!("بدء الاتصال...");\n                self.state = ConnectionState::Connecting;\n            }\n            ConnectionState::Connecting => {\n                printl                

المدونات

توصيات الكتب