Rust में उन्नत स्तर पर डिज़ाइन पैटर्न: कोड उदाहरण

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

Rust में डिज़ाइन पैटर्न: उदाहरणों के साथ उन्नत स्तर

\n\n

डिज़ाइन पैटर्न सामान्य समस्याओं के सिद्ध समाधान हैं जो लचीली, रखरखाव योग्य और स्केलेबल आर्किटेक्चर बनाने में मदद करते हैं। Rust में, इसके स्वामित्व, उधार और ट्रेट्स की प्रणाली के साथ, कई क्लासिक पैटर्न एक अद्वितीय कार्यान्वयन प्राप्त करते हैं। इस लेख में, हम उन्नत डिज़ाइन पैटर्न पर चर्चा करेंगे जो Rust इकोसिस्टम में विशेष रूप से प्रभावी हैं।

\n\n

1. उन्नत Builder (बिल्डर)

\n\n

Rust में क्लासिक Builder पैटर्न अक्सर विधियों की एक श्रृंखला के माध्यम से कार्यान्वित किया जाता है जो &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                println!("पहले से ही कनेक्ट हो रहा है...");\n            }\n            ConnectionState::Connected => {\n                println!("पहले से ही कनेक्टेड है।");\n            }\n        }\n    }\n\n    pub fn disconnect(&mut self) {\n        match self.state {\n            ConnectionState::Connected | ConnectionState::Connecting => {\n                println!("डिस्कनेक्ट हो रहा है...");\n                self.state = ConnectionState::Disconnected;\n            }\n            ConnectionState::Disconnected => {\n                println!("पहले से ही डिस्कनेक्टेड है।");\n            }\n        }\n    }\n}\n\nfn main() {\n    let mut conn = Connection::new();\n    conn.connect();\n    conn.connect();\n    conn.disconnect();\n}
\n\n

लाभ: सभी संभावित स्थितियों को स्पष्ट रूप से संभाला जाता है, और कंपाइलर यह सुनिश्चित करता है कि सभी मामलों को कवर किया गया है।

ब्लॉग

पुस्तक अनुशंसाएँ