कोड डिजाइन करते समय, आपके पास दो विकल्प होते हैं।
- बस इसे पूरा करें, जिस स्थिति में आपके लिए कोई समाधान काम करेगा
- पांडित्यपूर्ण होना और एक समाधान तैयार करना जो भाषा की विचित्रताओं को अपनी विचारधारा का शोषण करता है (इस मामले में ओओ भाषाएं - निर्णय प्रदान करने के लिए बहुरूपता का उपयोग के रूप में)
मैं पहले दो पर ध्यान केंद्रित नहीं करने जा रहा हूं, क्योंकि वास्तव में कुछ भी नहीं कहा जाना है। यदि आप इसे काम करने के लिए प्राप्त करना चाहते हैं, तो आप कोड को छोड़ सकते हैं जैसा कि यह है।
लेकिन क्या होगा, यदि आप इसे पांडित्यपूर्ण तरीके से करना चाहते हैं और वास्तव में डिजाइन पैटर्न के साथ समस्या को हल किया है, तो जिस तरह से आप चाहते थे?
आप निम्नलिखित प्रक्रिया को देख सकते हैं:
OO कोड को डिज़ाइन करते समय, अधिकांश if
s जो एक कोड में होते हैं , उनमें होना आवश्यक नहीं है। स्वाभाविक रूप से, यदि आप दो स्केलर प्रकारों की तुलना करना चाहते हैं, जैसे कि int
एस या float
एस, तो आपके पास होने की संभावना है if
, लेकिन यदि आप कॉन्फ़िगरेशन के आधार पर प्रक्रियाओं को बदलना चाहते हैं, तो आप जो चाहते हैं उसे प्राप्त करने के लिए बहुरूपता का उपयोग कर सकते हैं, निर्णय ले सकते हैं (फैसले) if
आपके व्यवसाय तर्क से एक जगह पर, जहां वस्तुओं को तत्काल - कारखानों को दिया जाता है ।
अब तक, आपकी प्रक्रिया 4 अलग-अलग रास्तों से गुजर सकती है:
data
न तो एन्क्रिप्ट किया गया है और न ही संपीड़ित (कॉल नॉट, रिटर्न data
)
data
संकुचित है (कॉल करें compress(data)
और इसे वापस लौटाएं)
data
एन्क्रिप्ट किया गया है (कॉल करें encrypt(data)
और इसे वापस करें )
data
संकुचित और एन्क्रिप्टेड है (कॉल करें encrypt(compress(data))
और इसे वापस करें )
सिर्फ 4 रास्तों को देखकर आपको एक समस्या का पता चलता है।
आपके पास एक प्रक्रिया है जो 3 को कॉल करती है (सैद्धांतिक रूप से 4, यदि आप किसी चीज़ को एक के रूप में नहीं बुलाते हैं) विभिन्न तरीकों से जो डेटा में हेरफेर करते हैं और फिर इसे वापस करते हैं। विधियों के अलग-अलग नाम हैं , अलग-अलग तथाकथित पब्लिक एपीआई (जिस तरह से तरीके उनके व्यवहार को संप्रेषित करते हैं)।
एडेप्टर पैटर्न का उपयोग करके , हम नाम कोशन (हम सार्वजनिक एपीआई को एकजुट कर सकते हैं) को हल कर सकते हैं जो कि गलत हो गया है। बस कहा, एडेप्टर दो असंगत इंटरफेस को एक साथ काम करने में मदद करता है। इसके अलावा, एडेप्टर एक नए एडेप्टर इंटरफ़ेस को परिभाषित करके काम करता है, जो कक्षाएं उनके एपीआई कार्यान्वयन को एकजुट करने की कोशिश कर रही हैं।
यह कोई ठोस भाषा नहीं है। यह एक सामान्य दृष्टिकोण है, किसी भी कीवर्ड का प्रतिनिधित्व करने के लिए यह किसी भी प्रकार का हो सकता है, सी # जैसी भाषा में आप इसे जेनरिक ( <T>
) के साथ बदल सकते हैं ।
मैं मान कर चल रहा हूं, कि अभी आपके पास संपीड़न और एन्क्रिप्शन के लिए जिम्मेदार दो वर्ग हो सकते हैं।
class Compression
{
Compress(data : any) : any { ... }
}
class Encryption
{
Encrypt(data : any) : any { ... }
}
एक उद्यम की दुनिया में, यहां तक कि इन विशिष्ट वर्गों को इंटरफेस द्वारा प्रतिस्थापित किए जाने की बहुत संभावना है, जैसे कि class
कीवर्ड को प्रतिस्थापित किया जाएगा interface
(क्या आपको C #, Java और / या PHP जैसी भाषाओं से निपटना चाहिए) या class
कीवर्ड रहेगा, लेकिन कीवर्ड Compress
और Encrypt
तरीकों को एक शुद्ध आभासी के रूप में परिभाषित किया जाएगा , आपको सी ++ में कोड करना चाहिए।
एडेप्टर बनाने के लिए, हम एक सामान्य इंटरफ़ेस परिभाषित करते हैं।
interface DataProcessing
{
Process(data : any) : any;
}
फिर हमें इसे उपयोगी बनाने के लिए इंटरफ़ेस का कार्यान्वयन प्रदान करना होगा।
// when neither encryption nor compression is enabled
class DoNothingAdapter : DataProcessing
{
public Process(data : any) : any
{
return data;
}
}
// when only compression is enabled
class CompressionAdapter : DataProcessing
{
private compression : Compression;
public Process(data : any) : any
{
return this.compression.Compress(data);
}
}
// when only encryption is enabled
class EncryptionAdapter : DataProcessing
{
private encryption : Encryption;
public Process(data : any) : any
{
return this.encryption.Encrypt(data);
}
}
// when both, compression and encryption are enabled
class CompressionEncryptionAdapter : DataProcessing
{
private compression : Compression;
private encryption : Encryption;
public Process(data : any) : any
{
return this.encryption.Encrypt(
this.compression.Compress(data)
);
}
}
ऐसा करने से, आप 4 वर्गों के साथ समाप्त होते हैं, प्रत्येक कुछ पूरी तरह से अलग करते हैं, लेकिन उनमें से प्रत्येक एक ही सार्वजनिक एपीआई प्रदान करते हैं। Process
विधि।
आपके व्यावसायिक तर्क में, जहाँ आप कोई भी / एन्क्रिप्शन / कम्प्रेशन / दोनों निर्णय नहीं लेते हैं, आप अपने ऑब्जेक्ट को उस DataProcessing
डिज़ाइन पर बनाएंगे जिसे हम पहले डिज़ाइन किए गए इंटरफ़ेस पर निर्भर करते हैं ।
class DataService
{
private dataProcessing : DataProcessing;
public DataService(dataProcessing : DataProcessing)
{
this.dataProcessing = dataProcessing;
}
}
यह प्रक्रिया तब भी इस प्रकार सरल हो सकती है:
public ComplicatedProcess(data : any) : any
{
data = this.dataProcessing.Process(data);
// ... perhaps work with the data
return data;
}
और कोई शर्त नहीं। कक्षा DataService
को इस बात का कोई पता नहीं है कि dataProcessing
सदस्य के पास जाने पर डेटा के साथ वास्तव में क्या किया जाएगा , और यह वास्तव में इसकी परवाह नहीं करता है, यह इसकी जिम्मेदारी नहीं है।
आदर्श रूप से, आपके पास 4 एडेप्टर कक्षाओं का परीक्षण करने के लिए आपके द्वारा बनाए गए यूनिट परीक्षण होंगे, यह सुनिश्चित करने के लिए कि वे काम करते हैं, आप अपना टेस्ट पास करते हैं। और यदि वे पास हो जाते हैं, तो आपको पूरा यकीन है कि वे आपके कोड में उन्हें कॉल करने पर कोई फर्क नहीं पड़ेगा।
तो क्या इस तरह if
से करना मेरे कोड में कभी नहीं होगा ?
नहीं, आपके व्यावसायिक तर्क में सशर्त होने की संभावना कम है, लेकिन वे अभी भी कहीं न कहीं हैं। जगह तुम्हारे कारखाने हैं।
और यह अच्छा है। आप सृजन की चिंताओं को अलग करते हैं और वास्तव में कोड का उपयोग करते हैं। यदि आप अपने कारखानों को विश्वसनीय बनाते हैं (जावा में आप Google द्वारा गुइसे ढांचे की तरह कुछ का उपयोग करके भी जा सकते हैं ), तो अपने व्यावसायिक तर्क में आप सही वर्ग को इंजेक्शन लगाने के बारे में चिंतित नहीं हैं। क्योंकि आप जानते हैं कि आपके कारखाने काम करते हैं और जो मांगे जाते हैं उसे वितरित करेंगे।
क्या इन सभी वर्गों, इंटरफेस इत्यादि का होना आवश्यक है?
यह हमें भीख मांगने के लिए वापस लाता है।
ओओपी में, यदि आप बहुरूपता का उपयोग करने के लिए पथ चुनते हैं, तो वास्तव में डिज़ाइन पैटर्न का उपयोग करना चाहते हैं, भाषा की सुविधाओं का दोहन करना चाहते हैं और / या सब कुछ का पालन करना चाहते हैं एक वस्तु विचारधारा है, तो यह है। और फिर भी, यह उदाहरण उन सभी कारखानों को भी नहीं दिखाता है जिनकी आपको आवश्यकता है और यदि आप उन्हें Compression
और Encryption
कक्षाओं को फिर से भरना और उन्हें इंटरफेस बनाना चाहते हैं, तो आपको उनके कार्यान्वयन को भी शामिल करना होगा।
अंत में आप सैकड़ों छोटी कक्षाओं और इंटरफेस के साथ अंत करते हैं, बहुत विशिष्ट चीजों पर ध्यान केंद्रित करते हैं। जो जरूरी नहीं कि बुरा हो, लेकिन आपके लिए सबसे अच्छा समाधान नहीं हो सकता है यदि आप चाहते हैं कि दो नंबर जोड़कर कुछ सरल करना है।
यदि आप इसे जल्दी से पूरा करना चाहते हैं, तो आप Ixrec के समाधान को पकड़ सकते हैं , जो कम से कम else if
और else
ब्लॉकों को खत्म करने में कामयाब रहे , जो, मेरी राय में, एक सादे से भी बदतर हैं if
।
ध्यान रखें कि यह अच्छा OO डिजाइन बनाने का मेरा तरीका है। कार्यान्वयन के बजाय इंटरफेस के लिए कोडिंग, यह है कि मैंने पिछले कुछ वर्षों से इसे कैसे किया है और यह दृष्टिकोण है जिसके साथ मैं सबसे अधिक आरामदायक हूं।
मैं व्यक्तिगत रूप से अगर-कम प्रोग्रामिंग को अधिक पसंद करता हूं और कोड की 5 लाइनों पर अधिक समाधान की सराहना करता हूं। यह जिस तरह से मुझे कोड डिजाइन करने के लिए उपयोग किया जाता है और मैं इसे पढ़ने में बहुत सहज हूं।
अद्यतन 2: मेरे समाधान के पहले संस्करण के बारे में एक जंगली चर्चा हुई है। चर्चा ज्यादातर मेरे कारण हुई, जिसके लिए मैं माफी मांगता हूं।
मैंने जवाब को इस तरह से संपादित करने का फैसला किया कि यह समाधान को देखने के तरीकों में से एक है, लेकिन केवल एक ही नहीं। मैंने डेकोरेटर भाग को भी हटा दिया, जहां मेरा मतलब था कि इसके बजाय, जिसे मैंने अंत में पूरी तरह से छोड़ने का फैसला किया, क्योंकि एक एडेप्टर एक मुखौटा भिन्नता है।
if
बयान होने की संभावना है ?