क्या झंडे की जांच करने की आवश्यकता को दूर करने के लिए एक डिज़ाइन पैटर्न है?


28

मैं डेटाबेस में कुछ स्ट्रिंग पेलोड को बचाने जा रहा हूं। मेरे पास दो वैश्विक कॉन्फ़िगरेशन हैं:

  • एन्क्रिप्शन
  • दबाव

इन्हें कॉन्फ़िगरेशन का उपयोग करके इस तरह से सक्षम या अक्षम किया जा सकता है कि दोनों में से केवल एक सक्षम है, दोनों सक्षम हैं या दोनों अक्षम हैं।

मेरा वर्तमान कार्यान्वयन यह है:

if (encryptionEnable && !compressEnable) {
    encrypt(data);
} else if (!encryptionEnable && compressEnable) {
    compress(data);
} else if (encryptionEnable && compressEnable) {
    encrypt(compress(data));
} else {
  data;
}

मैं डेकोरेटर पैटर्न के बारे में सोच रहा हूं। क्या यह सही विकल्प है, या शायद एक बेहतर विकल्प है?


5
वर्तमान में आपके पास क्या गलत है? क्या इस कार्यक्षमता के लिए आवश्यकताओं को बदलने की संभावना है? IE, नए ifबयान होने की संभावना है ?
डेरेन यंग

नहीं, मैं कोड को बेहतर बनाने के लिए किसी अन्य समाधान को देख रहा हूं।
दिमिथ गनेगोड़ा

46
आप इस बारे में पीछे की ओर जा रहे हैं। आपको एक पैटर्न नहीं मिलता है तो पैटर्न को फिट करने के लिए कोड लिखें। आप अपनी आवश्यकताओं को पूरा करने के लिए कोड लिखते हैं, फिर वैकल्पिक रूप से अपने कोड का वर्णन करने के लिए एक पैटर्न का उपयोग करते हैं।
मोनिका

1
ध्यान दें कि यदि आप मानते हैं कि आपका प्रश्न वास्तव में इस एक का डुप्लिकेट है , तो एक प्रश्नकर्ता के रूप में आपके पास हाल ही में खुले हुए "ओवरराइड" करने का एक विकल्प है और इसे ऐसे ही बंद कर दें। मैंने अपने कुछ सवालों के लिए यह किया और यह एक आकर्षण की तरह काम करता है। यहां मैंने यह कैसे किया, 3 आसान चरण - मेरे "निर्देशों" के साथ एकमात्र अंतर यह है कि चूंकि आपके पास 3K से कम प्रतिनिधि है, इसलिए आपको "डुप्लिकेट" विकल्प प्राप्त करने के लिए ध्वज संवाद से गुजरना होगा
gnat

8
@LightnessRacesinOrbit: आप जो कहते हैं उसमें कुछ सच्चाई है, लेकिन यह पूछना पूरी तरह से उचित है कि क्या किसी के कोड को तैयार करने का एक बेहतर तरीका है, और एक प्रस्तावित बेहतर संरचना का वर्णन करने के लिए डिज़ाइन पैटर्न को लागू करना पूरी तरह से उचित है। (फिर भी, मैं मानता हूं कि डिज़ाइन पैटर्न के लिए पूछने के लिए यह एक XY समस्या का एक सा है। आप जो चाहते हैं वह एक डिज़ाइन है , जो किसी भी ज्ञात पैटर्न का सख्ती से पालन कर सकता है या नहीं भी कर सकता है।) इसके अलावा, यह "पैटर्न" के लिए वैध है। अपने कोड को थोड़ा प्रभावित करें, इसमें यदि आप एक प्रसिद्ध पैटर्न का उपयोग कर रहे हैं, तो यह अक्सर आपके घटकों को तदनुसार नाम देने के लिए समझ में आता है।
रुख

जवाबों:


15

कोड डिजाइन करते समय, आपके पास दो विकल्प होते हैं।

  1. बस इसे पूरा करें, जिस स्थिति में आपके लिए कोई समाधान काम करेगा
  2. पांडित्यपूर्ण होना और एक समाधान तैयार करना जो भाषा की विचित्रताओं को अपनी विचारधारा का शोषण करता है (इस मामले में ओओ भाषाएं - निर्णय प्रदान करने के लिए बहुरूपता का उपयोग के रूप में)

मैं पहले दो पर ध्यान केंद्रित नहीं करने जा रहा हूं, क्योंकि वास्तव में कुछ भी नहीं कहा जाना है। यदि आप इसे काम करने के लिए प्राप्त करना चाहते हैं, तो आप कोड को छोड़ सकते हैं जैसा कि यह है।

लेकिन क्या होगा, यदि आप इसे पांडित्यपूर्ण तरीके से करना चाहते हैं और वास्तव में डिजाइन पैटर्न के साथ समस्या को हल किया है, तो जिस तरह से आप चाहते थे?

आप निम्नलिखित प्रक्रिया को देख सकते हैं:

OO कोड को डिज़ाइन करते समय, अधिकांश ifs जो एक कोड में होते हैं , उनमें होना आवश्यक नहीं है। स्वाभाविक रूप से, यदि आप दो स्केलर प्रकारों की तुलना करना चाहते हैं, जैसे कि intएस या floatएस, तो आपके पास होने की संभावना है if, लेकिन यदि आप कॉन्फ़िगरेशन के आधार पर प्रक्रियाओं को बदलना चाहते हैं, तो आप जो चाहते हैं उसे प्राप्त करने के लिए बहुरूपता का उपयोग कर सकते हैं, निर्णय ले सकते हैं (फैसले) ifआपके व्यवसाय तर्क से एक जगह पर, जहां वस्तुओं को तत्काल - कारखानों को दिया जाता है

अब तक, आपकी प्रक्रिया 4 अलग-अलग रास्तों से गुजर सकती है:

  1. dataन तो एन्क्रिप्ट किया गया है और न ही संपीड़ित (कॉल नॉट, रिटर्न data)
  2. dataसंकुचित है (कॉल करें compress(data)और इसे वापस लौटाएं)
  3. dataएन्क्रिप्ट किया गया है (कॉल करें encrypt(data)और इसे वापस करें )
  4. 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: मेरे समाधान के पहले संस्करण के बारे में एक जंगली चर्चा हुई है। चर्चा ज्यादातर मेरे कारण हुई, जिसके लिए मैं माफी मांगता हूं।

मैंने जवाब को इस तरह से संपादित करने का फैसला किया कि यह समाधान को देखने के तरीकों में से एक है, लेकिन केवल एक ही नहीं। मैंने डेकोरेटर भाग को भी हटा दिया, जहां मेरा मतलब था कि इसके बजाय, जिसे मैंने अंत में पूरी तरह से छोड़ने का फैसला किया, क्योंकि एक एडेप्टर एक मुखौटा भिन्नता है।


28
मैंने डाउनवोट नहीं किया लेकिन औचित्य नए वर्गों / इंटरफेसों की हास्यास्पद राशि हो सकती है कि कुछ करने के लिए मूल कोड 8 लाइनों में किया गया था (और दूसरा जवाब 5 में किया था)। मेरी राय में केवल एक चीज जो इसे पूरा करती है वह कोड के लिए सीखने की अवस्था को बढ़ा रही है।
मारीसी

6
@Maurycy ओपी ने जो पूछा, वह इस तरह के समाधान मौजूद होने पर सामान्य डिजाइन पैटर्न का उपयोग करके अपनी समस्या का समाधान खोजने की कोशिश करना था। क्या मेरा समाधान उसके या Ixrec के कोड से अधिक लंबा है? यह है। मैं ऐसा मानता हूं। क्या मेरा समाधान डिज़ाइन पैटर्न का उपयोग करके उसकी समस्या को हल करता है और इस प्रकार उसके प्रश्न का उत्तर देता है और प्रक्रिया से सभी आवश्यक इफ़ेक्ट को प्रभावी ढंग से हटाता है? ऐसा होता है। Ixrec की नहीं।
एंडी

26
मेरा मानना ​​है कि लेखन कोड जो स्पष्ट, विश्वसनीय, संक्षिप्त, निष्पादक और अनुरक्षण योग्य है वह जाने का मार्ग है। अगर मेरे पास हर बार किसी के लिए एक डॉलर होता था, तो वह अपने लक्ष्यों और उनके औचित्य को स्पष्ट रूप से व्यक्त किए बिना एक सॉफ्टवेयर पैटर्न का हवाला देता था या उद्धृत करता था, मैं एक अमीर आदमी होता।
रॉबर्ट हार्वे

12
मुझे लगता है कि मेरे पास दो मुद्दे हैं जो मैं यहां देख रहा हूं। पहला यह है कि Compressionऔर Encryptionइंटरफेस पूरी तरह से बहुत ही शानदार हैं। मुझे यकीन नहीं है कि अगर आप यह सुझाव दे रहे हैं कि वे किसी तरह से सजावट की प्रक्रिया के लिए आवश्यक हैं, या केवल यह अर्थ है कि वे निकाले गए अवधारणाओं का प्रतिनिधित्व करते हैं। दूसरा मुद्दा यह है कि CompressionEncryptionDecoratorओपी की स्थिति के समान एक वर्ग को दहनशील विस्फोट की ओर ले जाता है। मैं यह भी सुझाव दिया कोड में डेकोरेटर पैटर्न स्पष्ट रूप से पर्याप्त नहीं देख रहा हूँ।
कोबजार

5
SOLID बनाम सरल पर बहस इस बिंदु को याद कर रही है: यह कोड न तो है, और यह डेकोरेटर पैटर्न का भी उपयोग नहीं करता है। कोड स्वतः ही SOLID नहीं है क्योंकि यह इंटरफेस का एक गुच्छा उपयोग करता है। एक DataProcessing इंटरफ़ेस की निर्भरता इंजेक्शन थोड़े अच्छा है; बाकी सब कुछ शानदार है। SOLID एक वास्तुकला-स्तर की चिंता है जिसका उद्देश्य परिवर्तन को अच्छी तरह से संभालना है। ओपी ने अपनी वास्तुकला के बारे में कोई जानकारी नहीं दी और न ही वह अपने कोड को बदलने की उम्मीद करता है, इसलिए हम वास्तव में एक उत्तर में SOLID पर भी चर्चा नहीं कर सकते हैं।
कार्ल लेथ

120

एकमात्र समस्या जो मुझे आपके वर्तमान कोड के साथ दिख रही है, वह है कॉम्बिनेटरियल विस्फोट का जोखिम, क्योंकि आप अधिक सेटिंग्स जोड़ते हैं, जिसे आसानी से कोड को इस तरह से संरचित करके कम किया जा सकता है:

if(compressEnable){
  data = compress(data);
}
if(encryptionEnable) {
  data = encrypt(data);
}
return data;

मैं किसी भी "डिजाइन पैटर्न" या "मुहावरा" से अवगत नहीं हूं कि इसे एक उदाहरण माना जा सकता है।


18
@DamithGanegoda नहीं, अगर आप मेरे कोड को ध्यान से पढ़ेंगे तो आप देखेंगे कि यह उस मामले में ठीक यही काम करता है। इसीलिए elseअगर बयानों में मेरे दोनों के बीच कोई बात नहीं है, और मैं dataहर बार काम क्यों कर रहा हूँ । यदि दोनों झंडे सत्य हैं, तो संपीड़ित () निष्पादित हो जाता है, तो एन्क्रिप्ट () संपीड़ित के परिणाम पर निष्पादित हो जाता है (), जैसा आप चाहते हैं।
Ixrec

14
@DavidPacker तकनीकी रूप से, ऐसा हर प्रोग्रामिंग भाषा में बयान करने पर होता है। मैं सादगी के लिए गया था, क्योंकि यह एक समस्या की तरह लग रहा था जहां एक बहुत ही सरल उत्तर उपयुक्त था। आपका समाधान भी मान्य है, लेकिन व्यक्तिगत रूप से मैं इसे तब बचाऊंगा जब मेरे पास चिंता करने के लिए दो से अधिक बुलियन झंडे हों।
Ixrec

15
@DavidPacker: सही यह परिभाषित नहीं करता है कि कुछ लेखक द्वारा कुछ प्रोग्रामिंग विचारधारा के बारे में कुछ दिशानिर्देशों को कोड कितनी अच्छी तरह पालन करता है। सही है "कोड वह करता है जो उसे करना चाहिए था और क्या यह उचित समय में लागू किया गया था"। यदि यह इसे "गलत तरीके" से करने के लिए समझ में आता है, तो गलत तरीका सही तरीका है क्योंकि समय पैसा है।
18

9
@DavidPacker: अगर मैं ओपी की स्थिति में था, और उस सवाल से पूछा, ऑर्बिट की टिप्पणी में लाइटनेस रेस वह है जो मुझे वास्तव में चाहिए। "डिजाइन पैटर्न का उपयोग करके समाधान खोजना" पहले से ही गलत पैर से शुरू हो रहा है।
whatsisname

6
@DavidPacker वास्तव में यदि आप प्रश्न को अधिक बारीकी से पढ़ते हैं, तो यह एक पैटर्न पर जोर नहीं देता है। इसमें कहा गया है, "मैं डेकोरेटर पैटर्न के बारे में सोच रहा हूं। क्या यह सही विकल्प है या शायद कोई बेहतर विकल्प है?" । आपने मेरे उद्धरण में पहला वाक्य संबोधित किया, लेकिन दूसरा नहीं। अन्य लोगों ने दृष्टिकोण लिया कि नहीं, यह सही विकल्प नहीं है। फिर आप यह दावा नहीं कर सकते कि केवल आपका ही सवाल का जवाब है।
जॉन बेंटले

12

मुझे लगता है कि आपका प्रश्न व्यावहारिकता की तलाश में नहीं है, इस मामले में lxrec का उत्तर सही है, लेकिन डिज़ाइन पैटर्न के बारे में जानने के लिए।

जाहिर है कि कमांड पैटर्न एक ऐसी तुच्छ समस्या के लिए एक ओवरकिल है, जैसा कि आप प्रस्तावित करते हैं, लेकिन उदाहरण के लिए यह यहाँ जाता है:

public interface Command {
    public String transform(String s);
}

public class CompressCommand implements Command {
    @Override
    public String transform(String s) {
        String compressedString=null;
        //Compression code here
        return compressedString;
    }
}

public class EncryptCommand implements Command {
    @Override
    public String transform(String s) {
        String EncrytedString=null;
        // Encryption code goes here
        return null;
    }

}

public class Test {
    public static void main(String[] args) {
        List<Command> commands = new ArrayList<Command>();
        commands.add(new CompressCommand());
        commands.add(new EncryptCommand()); 
        String myString="Test String";
        for (Command c: commands){
            myString = c.transform(myString);
        }
        // now myString can be stored in the database
    }
}

जैसा कि आप एक सूची में आदेश / परिवर्तन डालते हुए देखते हैं कि उपचार के लिए क्रमिक रूप से निष्पादित किया जा सकता है। जाहिर है कि यह दोनों को निष्पादित करेगा, या उनमें से केवल एक पर निर्भर करेगा और यदि आप बिना किसी शर्त के सूची में डालते हैं।

जाहिर है कि सशर्त कुछ प्रकार के कारखाने में समाप्त हो जाएंगे जो कमांड सूची को एक साथ रखता है।

EDIT @ टेक्सक्रे की टिप्पणी के लिए:

यदि समाधान के सृजनात्मक भाग में स्थितियां हैं, तो इससे बचने के कई तरीके हैं, उदाहरण के लिए, डेस्कटॉप GUI ऐप का उपयोग करें । आप सेक और एन्क्रिप्ट विकल्पों के लिए चेकबॉक्स हो सकते हैं। on clicउन चेकबॉक्सों की स्थिति में आप संबंधित कमांड को तुरंत इंस्टाल करते हैं और इसे सूची में जोड़ते हैं, या यदि आप विकल्प को रद्द कर रहे हैं तो सूची से हटा दें।


जब तक आप "बिना किसी प्रकार के कारखाने की एक सूची प्रदान कर सकते हैं जो कि कमांड लिस्ट को एक साथ रखे" कोड के बिना अनिवार्य रूप से Ixrec के उत्तर की तरह दिखता है तो IMO इस प्रश्न का उत्तर नहीं देता है। यह संपीड़ित और एन्क्रिप्ट कार्यों को लागू करने का एक बेहतर तरीका प्रदान करता है, लेकिन झंडे से बचने के लिए नहीं।
Thexacre 19

@thexacre मैंने एक उदाहरण जोड़ा।
ट्यूलेंस कोर्डोवा

तो अपने चेकबॉक्स ईवेंट श्रोता में आपके पास "अगर चेकबॉक्स है। तो फिर कमांड जोड़ें"? ऐसा लगता है जैसे आप सिर्फ झंडे को
हिला

@thexacre नहीं, प्रत्येक चेकबॉक्स के लिए एक श्रोता। केवल commands.add(new EncryptCommand()); या commands.add(new CompressCommand());क्रमशः क्लिक इवेंट में ।
ट्यूलेंस कोर्डोवा

बॉक्स को अनचेक करने से निपटने के बारे में क्या? लगभग हर भाषा / यूआई टूलकिट के बारे में मैंने अभी भी इवेंट श्रोता में चेकबॉक्स की स्थिति की जांच करने की आवश्यकता है। मैं मानता हूं कि यह एक बेहतर पैटर्न है, लेकिन यह मूल रूप से जरूरत से बचने से बचता है अगर झंडा कहीं पर कुछ करता है।
thexacre

7

मुझे लगता है कि "डिजाइन पैटर्न" अनावश्यक रूप से "ओओ पैटर्न" की ओर केंद्रित होते हैं और पूरी तरह से बहुत सरल विचारों से बचते हैं। हम यहां जिस बारे में बात कर रहे हैं वह एक सरल (सरल) डेटा पाइपलाइन है।

मैं इसे क्लोजर में करने की कोशिश करूंगा। कोई भी अन्य भाषा जहाँ फ़ंक्शंस प्रथम श्रेणी के होते हैं शायद ठीक है। हो सकता है कि मैं बाद में C # उदाहरण दे सकूं, लेकिन यह उतना अच्छा नहीं है। इसे सुलझाने का मेरा तरीका गैर-क्लोजरियन के लिए कुछ स्पष्टीकरणों के साथ निम्नलिखित कदम होगा:

1. परिवर्तनों का एक सेट का प्रतिनिधित्व करें।

(def transformations { :encrypt  (fn [data] ... ) 
                       :compress (fn [data] ... )})

यह एक मानचित्र है, अर्थात् कीवर्ड से फ़ंक्शंस तक एक लुकअप टेबल / शब्दकोश / जो भी हो। एक अन्य उदाहरण (स्ट्रिंग्स के लिए कीवर्ड):

(def employees { :A1 "Alice" 
                 :X9 "Bob"})

(employees :A1) ; => "Alice"
(:A1 employees) ; => "Alice"

तो, लेखन (transformations :encrypt)या (:encrypt transformations)एन्क्रिप्ट फ़ंक्शन को वापस करेगा। ( (fn [data] ... )सिर्फ एक लंबोतरा फ़ंक्शन है।)

2. कीवर्ड के अनुक्रम के रूप में विकल्प प्राप्त करें:

(defn do-processing [options data] ;function definition
  ...)

(do-processing [:encrypt :compress] data) ;call to function

3. आपूर्ति किए गए विकल्पों का उपयोग करके सभी परिवर्तनों को फ़िल्टर करें।

(let [ transformations-to-run (map transformations options)] ... )

उदाहरण:

(map employees [:A1]) ; => ["Alice"]
(map employees [:A1 :X9]) ; => ["Alice", "Bob"]

4. कार्यों को एक में मिलाएं:

(apply comp transformations-to-run)

उदाहरण:

(comp f g h) ;=> f(g(h()))
(apply comp [f g h]) ;=> f(g(h()))

5. और फिर एक साथ:

(def transformations { :encrypt  (fn [data] ... ) 
                       :compress (fn [data] ... )})

(defn do-processing [options data]
  (let [transformations-to-run (map transformations options)
        selected-transformations (apply comp transformations-to-run)] 
    (selected-transformations data)))

(do-processing [:encrypt :compress])

यदि हम एक नया फ़ंक्शन जोड़ना चाहते हैं, तो केवल "डिबग-प्रिंट" कहते हैं, निम्नलिखित परिवर्तन है:

(def transformations { :encrypt  (fn [data] ... ) 
                       :compress (fn [data] ... )
                       :debug-print (fn [data] ...) }) ;<--- here to add as option

(defn do-processing [options data]
  (let [transformations-to-run (map transformations options)
        selected-transformations (apply comp transformations-to-run)] 
    (selected-transformations data)))

(do-processing [:encrypt :compress :debug-print]) ;<-- here to use it
(do-processing [:compress :debug-print]) ;or like this
(do-processing [:encrypt]) ;or like this

फंक को केवल उन कार्यों में शामिल किया जाता है, जिन्हें एक तरह से या किसी अन्य रूप में बयानों की एक श्रृंखला का उपयोग किए बिना अनिवार्य रूप से लागू करने की आवश्यकता होती है?
thexacre 19

पंक्ति funcs-to-run-here (map options funcs)फ़िल्टरिंग कर रही है, इस प्रकार लागू करने के लिए फ़ंक्शन का एक सेट चुनना है। शायद मुझे जवाब अपडेट करना चाहिए और थोड़ा और विस्तार में जाना चाहिए।
NiklasJ

5

[अनिवार्य रूप से, मेरा उत्तर ऊपर दिए गए @Ixrec द्वारा उत्तर पर अनुवर्ती है । ]

एक महत्वपूर्ण प्रश्न: विभिन्न संयोजनों की संख्या है जिसे आपको कवर करने की आवश्यकता है, बढ़ने जा रहा है? आप अपने विषय डोमेन के बारे में बेहतर जानते हैं। यह आपका निर्णय है।
क्या वेरिएंट की संख्या संभवतः बढ़ सकती है? खैर, यह समझ से बाहर नहीं है। उदाहरण के लिए, आपको अधिक भिन्न एन्क्रिप्शन एल्गोरिदम को समायोजित करने की आवश्यकता हो सकती है।

यदि आप अनुमान लगाते हैं कि विभिन्न संयोजनों की संख्या बढ़ने जा रही है, तो रणनीति पैटर्न आपकी मदद कर सकता है। यह एल्गोरिदम को एनकैप्सुलेट करने और कॉलिंग कोड के लिए एक विनिमेय इंटरफ़ेस प्रदान करने के लिए डिज़ाइन किया गया है। आपके पास तब भी कम मात्रा में तर्क होगा जब आप प्रत्येक विशेष स्ट्रिंग के लिए उपयुक्त रणनीति बनाते हैं (त्वरित)।

आपने ऊपर टिप्पणी की है कि आप अपेक्षाएं बदलने की अपेक्षा नहीं करते हैं। यदि आप यह उम्मीद नहीं करते हैं कि वेरिएंट की संख्या बढ़ेगी (या यदि आप इस रीफैक्टरिंग को स्थगित कर सकते हैं), तो तर्क को उसी तरह रखें। वर्तमान में, आपके पास तर्क की एक छोटी और प्रबंधनीय राशि है। (शायद एक रणनीति पैटर्न के लिए एक संभव refactoring के बारे में टिप्पणी करने के लिए स्व पर ध्यान दें।)


1

स्कैला में ऐसा करने का एक तरीका होगा:

val handleCompression: AnyRef => AnyRef = data => if (compressEnable) compress(data) else data
val handleEncryption: AnyRef => AnyRef = data => if (encryptionEnable) encrypt(data) else data
val handleData = handleCompression andThen handleEncryption
handleData(data)

उपरोक्त लक्ष्यों को प्राप्त करने के लिए डेकोरेटर पैटर्न का उपयोग करना (व्यक्तिगत प्रसंस्करण तर्क को अलग करना और वे एक साथ तार कैसे करते हैं) बहुत अधिक क्रियात्मक होंगे।

जिसमें आपको एक OO प्रोग्रामिंग प्रतिमान में इन डिजाइन लक्ष्यों को प्राप्त करने के लिए एक डिज़ाइन पैटर्न की आवश्यकता होगी, कार्यात्मक भाषा प्रथम श्रेणी के नागरिकों (कोड 1 और पंक्ति में 2) और कार्यात्मक संरचना (पंक्ति 3) के रूप में कार्यों का उपयोग करके मूल समर्थन प्रदान करती है।


यह ओपी के दृष्टिकोण से बेहतर (या बदतर) क्यों है? और / या आप डेकोरेटर पैटर्न का उपयोग करने के लिए ओपी के विचार के बारे में क्या सोचते हैं?
कैस्पर वैन डेन बर्ग

यह कोड स्निपेट बेहतर है और ऑर्डर करने के बारे में स्पष्ट है (एन्क्रिप्शन से पहले संपीड़न); अवांछित इंटरफेस से बचा जाता है
राग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.