2009-01-30 16 views
10

क्या कोई अन्य डिज़ाइन पैटर्न/विधियों/नेस्टेड को हटाने के तरीके हैं तो क्या शर्तों/स्विच स्टेटमेंट्स?नेस्टेड से निपटने के लिए अगर अन्यथा/नेस्टेड स्विच स्टेटमेंट

मुझे Google कोड ब्लॉग पोस्ट में सूचीबद्ध Google लोगों द्वारा उपयोग की जाने वाली कुछ विधियों में आना याद है। अब यह प्रतीत नहीं होता है कि

+0

क्या आप एक उदाहरण दे सकते हैं? – Apocalisp

उत्तर

5

आप एक रिफैक्टरिंग का उपयोग करना चाहते हैं जो एक पॉलिमॉर्फिक कक्षा का उपयोग करके सशर्त को बदल देता है। example के लिए।

या यहाँ एक और example

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

संपादित

मुझे जोड़ने कि इस हर मामले में एक आदर्श समाधान नहीं है करते हैं। जैसा कि (मैं आपका नाम क्षमा चाहता हूं) मेरी टिप्पणियों में इंगित किया गया है, कुछ बार यह दर्द हो सकता है, खासकर यदि आपको ऐसा करने के लिए ऑब्जेक्ट मॉडल बनाना है। यह रिफैक्टरिंग excells आप इस अगर:

function doWork(object x) 
{ 

    if (x is a type of Apple) 
    { 
     x.Eat(); 

    } else if (x is a type of Orange) 
    { 
     x.Peel(); 
     x.Eat(); 
    } 

} 

यहाँ आप कुछ नया तरीका है कि प्रत्येक फल संभाल लेंगे में स्विच refactor कर सकते हैं।

संपादित

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

class FruitFactory 
{ 
    Fruit GetMeMoreFruit(typeOfFruit) 
    { 
     switch (typeOfFruit) 
     ... 
     ... 
    } 
} 

इस विधि की अच्छी बात यह लिखने के लिए आसान है, और आमतौर पर पहली विधि मैं उपयोग करते हैं: पहली और सबसे सीधे आगे (और हाँ इस सवाल का अनाज के खिलाफ जाता है) एक स्विच है। जबकि आपके पास अभी भी एक स्विच स्टेटमेंट है जो कोड के एक क्षेत्र से अलग है और यह बहुत ही बुनियादी है, यह सब एक रिटर्न है। यदि आपके पास केवल कुछ वस्तुएं हैं और वे; यह काम बहुत अच्छी तरह से नहीं बदल रहे हैं।

अन्य अधिक कॉम्पेक्स पैटर्न जो आप देख सकते हैं वह Abstract Factory है। यदि आपका मंच इसका समर्थन करता है तो आप गतिशील रूप से फल भी बना सकते हैं। आप Provider Pattern जैसे कुछ भी उपयोग कर सकते हैं। जो अनिवार्य रूप से मेरे लिए है, इसका मतलब है कि आप अपनी वस्तु को कॉन्फ़िगर करते हैं और फिर आपके पास एक कारखाना है जो कॉन्फ़िगरेशन पर आधारित होता है और एक कुंजी जो आप फैक्ट्री देते हैं, वह गतिशील रूप से सही कक्षा बनाती है।

+0

काम करता है यदि आपके पास ऑब्जेक्ट्स और पॉलिमॉर्फिज्म आसान है। दर्द यदि आप नहीं करते हैं। –

+0

हाँ काफी सही है अगर तर्क काफी सरल है तो यह दर्द के लायक नहीं हो सकता है ... लेकिन यदि सशर्त के प्रत्येक शरीर में बहुत कुछ चल रहा है तो बस इसे तोड़ने से जटिलता कम हो सकती है किसी भी समय चिंता करो। – JoshBerke

+0

doWork() ने सही प्रकार कैसे दिया है? –

1

आप कहते हैं कि नहीं है कि आप किस भाषा का प्रयोग कर रहे हैं, लेकिन अगर आप एक OO भाषा का प्रयोग कर रहे सी ++, C# या जावा, आप अक्सर आभासी कार्यों उपयोग कर सकते हैं के रूप में ही समस्या को हल करने के रूप में आप वर्तमान में हल करते है switch कथन के साथ, और एक अधिक विस्तारणीय तरीके से। सी ++ के मामले में, की तुलना:

class X { 
public: 
    int get_type();  /* Or an enum return type or similar */ 
    ... 
}; 

void eat(X& x) { 
    switch (x.get_type()) { 
    TYPE_A: eat_A(x); break; 
    TYPE_B: eat_B(x); break; 
    TYPE_C: eat_C(x); break; 
    } 
} 

void drink(X& x) { 
    switch (x.get_type()) { 
    TYPE_A: drink_A(x); break; 
    TYPE_B: drink_B(x); break; 
    TYPE_C: drink_C(x); break; 
    } 
} 

void be_merry(X& x) { 
    switch (x.get_type()) { 
    TYPE_A: be_merry_A(x); break; 
    TYPE_B: be_merry_B(x); break; 
    TYPE_C: be_merry_C(x); break; 
    } 
} 

साथ

class Base { 
    virtual void eat() = 0; 
    virtual void drink() = 0; 
    virtual void be_merry() = 0; 
    ... 
}; 

class A : public Base { 
public: 
    virtual void eat() { /* Eat A-specific stuff */ } 
    virtual void drink() { /* Drink A-specific stuff */ } 
    virtual void be_merry() { /* Be merry in an A-specific way */ } 
}; 

class B : public Base { 
public: 
    virtual void eat() { /* Eat B-specific stuff */ } 
    virtual void drink() { /* Drink B-specific stuff */ } 
    virtual void be_merry() { /* Be merry in an B-specific way */ } 
}; 

class C : public Base { 
public: 
    virtual void eat() { /* Eat C-specific stuff */ } 
    virtual void drink() { /* Drink C-specific stuff */ } 
    virtual void be_merry() { /* Be merry in a C-specific way */ } 
}; 

लाभ यह है कि आप किसी भी कोड को छूने के लिए बिना नई Base व्युत्पन्न वर्गों D, E, F और इतने पर जोड़ सकते हैं कि केवल Base पर पॉइंटर्स या संदर्भों से संबंधित है, इसलिए कुछ भी ऐसा नहीं है जो switch कथन मूल समाधान में हो सकता है।(परिवर्तन जावा में बहुत समान दिखता है, जहां विधियां डिफ़ॉल्ट रूप से आभासी होती हैं, और मुझे यकीन है कि यह सी # में भी समान दिखता है।) एक बड़ी परियोजना पर, यह विशाल रखरखाव जीत है।

+0

लोगों को डाउनवॉट क्यों करें? –

+0

शायद क्योंकि वर्चुअल फ़ंक्शंस हैं कि सी ++ पॉलिमॉर्फिज्म को कैसे लागू करता है; डरावनी ड्राइव से काउंटर ड्राइव के लिए +1 –

+0

@ स्टेवन: मुझे लगता है ...मुझे उम्मीद थी कि यह स्पष्ट होगा कि यह किसी ओओ भाषा में लागू होता है (मुझे पता है कि जावा संस्करण लगभग समान है, लेकिन इस तथ्य के लिए कि डिफ़ॉल्ट रूप से विधियां "आभासी" हैं, और यह शायद सी # के साथ समान है), लेकिन किसी भी मामले में मैंने इसे और अधिक स्पष्ट बनाने के लिए संपादित किया है। –

7

आप हॉरर कोडिंग से तीर कोड सपाट पर this पढ़ा है?

आप अपवाद के बिना एक भाषा का प्रयोग कर रहे हैं वापसी या गोटो के साथ फेंक बदल सकते हैं।

+1

+1 गार्ड क्लॉज नेस्टेड आईएफएस को कम करने और जल्दी से किसी फ़ंक्शन से बाहर निकलने का एक अच्छा तरीका है। आईएमएचओ पढ़ने के लिए बहुत साफ और आसान है। – JoshBerke

3

मैं वास्तव में कैसे 2008 के अप्रैल में अपने ब्लॉग में इस मुद्दे को सुलझाने एक नज़र here ले लो और मुझे पता है आप क्या सोचते हैं के बारे में लिखा था।

मैं तुम्हें सलाह देते हैं:

  1. उपयोग बहुरूपता सही रन-टाइम व्यवहार आप सशर्त बयान के बिना की जरूरत है पाने के लिए।

  2. अपने सभी सशर्त बयान लें, और उन्हें किसी प्रकार के "कारखाने" में ले जाएं जो आपको रन-टाइम पर उचित प्रकार का सौंप देगा।

  3. आप काम हो गया। क्या यह आसान नहीं था? :)

यदि आप अपने कोड को बदलने के तरीके पर कुछ वास्तविक कोड नमूना देखना चाहते हैं, तो मेरे ब्लॉग पर जाएं।

पीएस यह आत्म प्रचार में एक सस्ता प्रयास नहीं है; मैं अब बहुत समय से एक एसओ उपयोगकर्ता रहा हूं, और यह पहली बार है जब मैंने अपने ब्लॉग से लिंक किया है - और मैंने केवल ऐसा इसलिए किया है क्योंकि मुझे लगता है कि यह प्रासंगिक है। आप गूगल के "The Clean Code Talks -- Inheritance, Polymorphism, & Testing" वीडियो के बारे में सोच

+1

यदि आप आलेख को उद्धृत करते हैं, या कम से कम इस पोस्ट में मुख्य बिंदुओं पर हिट करते हैं (उपयोगकर्ता को लिंक पर क्लिक करने के लिए मजबूर करने के बजाय बस यह पता लगाने के लिए मजबूर करने के बजाय) तो आपको शायद अधिक अपवॉट मिलेगा ... –

+0

@Adam : हाँ, मैं सोच रहा था कि मुझे इस उत्तर के अपने पहले संपादन पर ऐसा करना चाहिए था, लेकिन देर हो चुकी है और मैं थक गया हूं। मैं आगे बढ़ गया और आपकी सलाह का पालन किया, हालांकि। धन्यवाद! –

+0

उपयोगी; हालांकि इसमें केवल 1 प्रकार का होता है यदि अन्य तीर – Adrian

2

कर रहे थे? यह कंडीशनर स्विच/स्विच करने के लिए ऑब्जेक्ट ओरिएंटेड तकनीकों का उपयोग करने के दृष्टिकोणों पर चर्चा करता है।

1

आप Strategy Pattern पर देख सकते हैं, जिसमें लिंक्ड स्थितियों के साथ आईएफएस की लंबी श्रृंखला डालने की बजाय, आप प्रत्येक शर्त को एक अलग वस्तु में सारणी देते हैं, प्रत्येक व्यक्ति इसका विशिष्ट व्यवहार परिभाषित करता है।

वर्ग कि उन वस्तुओं को परिभाषित करता है एक अंतरफलक जो पैरेंट ऑब्जेक्ट से बुलाया जाएगा लागू करेंगे।

+0

एक और भिन्नता टेम्पलेट पैटर्न है .... बहुत सिमिलर – JoshBerke

0

कैसे के बारे में:

/* Code Block 1... */ 

if(/* result of some condition or function call */) 
{ 
    /* Code Block 2... */ 

    if(/* result of some condition or function call */) 
    { 
     /* Code Block 3... */ 

     if(/* result of some condition or function call */) 
     { 
     /* Code Block 4... */ 
     } 
    } 
} 

इस बन जाता है:

/* Code Block 1... */ 
IsOk = /* result of some condition or function call */ 

if(IsOK) 
{ 
    /* Code Block 2... */ 
    IsOk = /* result of some condition or function call */ 
} 

if(IsOK) 
{ 
    /* Code Block 3...*/ 
    IsOk = /* result of some condition or function call */ 
} 

if(IsOK) 
{ 
    /* Code Block 4...*/ 
    IsOk = /* result of some condition or function call */ 
} 

/* And so on... */ 

आप कर सकते हैं पाठ्यक्रम वापसी की अगर कभी IsOk झूठा हो जाता है, यदि उपयुक्त।

संबंधित मुद्दे