2010-10-22 17 views
7

मैं enum है कहना ErrorCodes कि"अगर" बनाम बयान OO डिजाइन

public enum ErrorCodes { 
     INVALID_LOGIN(100), 
     INVALID_PASSWORD(101), 
     SESSION_EXPIRED(102) ...; 

     private int errorCode; 

     private ErrorCodes(int error){ 
       this.errorCode = error; 
     } //setter and getter and other codes 
} 

अब मैं इस त्रुटि कोड के साथ मेरी अपवाद त्रुटि कोड की जाँच करें। मैं यह नहीं लिखना चाहता हूं कि यह ऐसा करता है, अगर ऐसा होता है। मैं इस समस्या को कैसे हल कर सकता हूं (ब्लॉक के 10+ लिखना)

क्या उस स्थिति में कोई डिज़ाइन पटर है?

धन्यवाद

+0

क्या सिर्फ 'केस स्टेटमेंट' मदद कर रहा है या क्या मुझे कुछ याद आ रहा है? – Jean

+0

हाँ, इस तरह से आपको हर बार अपना कार्यान्वयन बदलना होगा, एनम परिवर्तन (उदाहरण के लिए नए केस स्टेटमेंट)। अच्छे ओओ डिज़ाइन के आधार पर अपना कोड लागू करते समय आपको एक्सटेंशन के लिए खुला होने का प्रयास करना चाहिए, लेकिन संशोधनों के लिए बंद होना चाहिए। – Mephisztoe

उत्तर

3

जैसा कि स्पोइक द्वारा इंगित किया गया है, सही त्रुटि हैंडलिंग विधि चुनने के लिए बहुरूपता का उपयोग करना एक विकल्प है। क्लास पदानुक्रम को परिभाषित करके, यह दृष्टिकोण मूल रूप से 10+ को अवरुद्ध करता है यदि JVM के वर्चुअल विधि लुकअप को ब्लॉक करता है।

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

उदाहरण के लिए, यदि आप प्रत्येक ErrorCode के लिए कोई दूसरा त्रुटि संदेश वापस करना चाहते, तो आप बस यह कर सकते हैं:

// Note singular name for enum 
public enum ErrorCode { 
    INVALID_LOGIN(100, "Your login is invalid"), 
    INVALID_PASSWORD(101, "Your password is invalid"), 
    SESSION_EXPIRED(102, "Your session has expired"); 

    private final int code; 
    private final String 

    private ErrorCode(int code, String message){ 
      this.code = code; 
      this.message = message; 
    } 

    public String getMessage() { 
     return message; 
    } 
} 

फिर अपने त्रुटि हैंडलिंग कोड सिर्फ हो जाता है:

ErrorCode errorCode = getErrorCode(); 
prompt(errorCode.getMessage()); 

एक दोष इस दृष्टिकोण का यह है कि यदि आप अतिरिक्त मामलों को जोड़ना चाहते हैं, तो आपको enum को संशोधित करने की आवश्यकता होगी, जबकि कक्षा पदानुक्रम के साथ आप मौजूदा कोड को संशोधित किए बिना नए मामले जोड़ सकते हैं।

+0

धन्यवाद मैंने अपनी समस्या हल की है बस इस विधि को जोड़ना: सार्वजनिक स्थैतिक स्ट्रिंग getErrorMessage (int errorCode); और ErrorCode.values ​​में संदेश ढूंढें। सबको धन्यवाद! –

+0

सुनने के लिए अच्छा :) – oksayt

+0

वैसे, यदि आप वर्तमान में सभी त्रुटि कोड लुकअप पर सभी तत्वों के माध्यम से looping कर रहे हैं, तो इस समाधान को जांचें जो इसे निरंतर समय में कर सकता है: http://stackoverflow.com/questions/ 2780129/get-enum-by-its-inner-field/2780170 # 2780170 – oksayt

2

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

रणनीति पैटर्न और खुले बंद सिद्धांत के लिए खोजें।

0

आप त्रुटि कोड (पूर्णांक) enum प्रकार के खिलाफ का एक नक्शा बना सकते हैं

संपादित

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

उदा।

Map<Integer, ErrorCodes> errorMap = new HashMap<Integer, ErrorCodes>(); 
for (ErrorCodes error : ErrorCodes.values()) { 
    errorMap.put(error.getCode(), error); 
} 

अब जब आप अपने aplpication से आ रही एक त्रुटि कोड की जांच करना चाहते, तुम सब करने की जरूरत है,

ErrorCodes error = errorMap.get(erro_code_from_application); 

इस प्रकार सभी if..else के लिए की जरूरत को हटाने।

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

+0

मुझे लगता है कि यह समाधान नहीं है। मेरा कोड अभी है लेकिन यह सिद्धांतों का पालन नहीं करता है। मेरा मतलब है, अगर बयान लिखते हैं: अगर() और यदि() और अगर() .... else() एक अच्छा समाधान नहीं है –

7

या तो आप इसे if-statement या स्विच के साथ करते हैं, या आप केवल तर्क में तर्क लागू करते हैं किसी भी तरह त्रुटि कोड में।

ओओ फैशन में यह सब इस बात पर निर्भर करता है कि आप कैसे चाहते हैं कि एप्लिकेशन या सिस्टम त्रुटि कोड पर प्रतिक्रिया करे। कहते हैं कि चलो तुम सिर्फ संवाद के उत्पादन में somekind के लिए यह चाहते हैं:

public doSomethingWithError() { 

    ErrorCodes e = getError(); 
    // the source of error, or originator, returns the enum 

    switch(e) { 
    case ErrorCodes.INVALID_LOGIN: 
     prompt('Invalid Login'); 
    case ErrorCodes.INVALID_PASSWORD: 
     prompt('Invalid password'); 
    // and so on 
    } 

} 

हम बजाय एक ErrorHandler वर्ग बना सकते हैं कि इस बजाय करता है:

// We'll implement this using OO instead 
public doSomethingWithError() { 

    ErrorHandler e = getError(); 
    // the originator now returns an ErrorHandler object instead 

    e.handleMessage(); 

} 

// We will need the following abstract class: 
public abstract class ErrorHandler { 

    // Lets say we have a prompter class that prompts the message 
    private Prompter prompter = new Prompter(); 

    public final void handleMessage() { 
    String message = this.getMessage(); 
    prompter.prompt(message); 
    } 

    // This needs to be implemented in subclasses because 
    // handleMessage() method is using it. 
    public abstract String getMessage(); 
} 

// And you'll have the following implementations, e.g. 
// for invalid logins: 
public final class InvalidLoginHandler() { 

    public final String getMessage() { 
    return "Invalid login"; 
    } 

} 

// E.g. for invalid password: 
public final class InvalidPasswordHandler() { 
    public final String getMessage() { 
    return "Invalid password"; 
    } 
} 

पूर्व समाधान लागू करने के लिए आसान है, लेकिन करना मुश्किल हो जाता बनाए रखें क्योंकि कोड बड़ा हो जाता है। बाद का समाधान अधिक जटिल है, (उर्फ Template Method patternOpen-Closed Principle के बाद) लेकिन आपको ErrorHandler में अधिक आवश्यकताएं जोड़ने की आवश्यकता होती है जब आपको इसकी आवश्यकता होती है (जैसे संसाधनों को बहाल करना या जो भी हो)। आप इसे Strategy pattern के साथ भी कार्यान्वित कर सकते हैं।

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

संपादित करें:

this answer by Michael Borgwardt और this answer by oksayt अगर आपको लगता है कि बजाय क्या करना चाहते हैं कैसे जावा Enums पर तरीकों को लागू करने के लिए देखें।

0

मेरी राय में त्रुटि कोड के साथ त्रुटि कोड और त्रुटि प्रबंधन को प्रेषित करने के लिए एक स्विच स्टेटमेंट में कुछ भी गलत नहीं है। Enums और स्विच वास्तव में अच्छी तरह से एक साथ फिट।

हालांकि, आपको निम्न insteresting (अधिक डिज़ाइन की तरह) मिल सकता है, an Example या "Double dispatching" on Wikipedia देखें। ग्रहण आवश्यकताओं:

  • त्रुटि-हैंडलिंग एक ही वर्ग में समाहित किया जाना चाहिए
  • त्रुटि-हैंडलिंग बदले होना चाहिए
  • प्रकार सुरक्षा: जब भी कोई त्रुटि जोड़ा जाता है, तो आप प्रत्येक पर निपटने त्रुटि जोड़ने के लिए मजबूर किया जाता है त्रुटि-हैंडलर कार्यान्वयन। एक (संभवतः कई) स्विच स्टेटमेंट में एक त्रुटि को "भूलना" संभव नहीं है।

कोड:

//Inteface for type-safe error handler 
interface ErrorHandler { 
    void handleInvalidLoginError(InvalidLoginError error); 
    void handleInvalidPasswordError(InvalidLoginError error); 
//One method must be added for each kind error. No chance to "forget" one. 
} 

//The error hierachy 
public class AbstractError(Exception) { 
    private int code; 
    abstract public void handle(ErrorHandler); 
} 
public class InvalidLoginError(AbstractError) { 
    private String additionalStuff; 
    public void handle(ErrorHandler handler) { 
     handler.handleInvalidLoginError(this); 
    } 
    public String getAdditionalStuff(); 
} 
public class InvalidPasswordError(AbstractError) { 
    private int code; 
    public void handle(ErrorHandler handler) { 
     handler.handleInvalidPasswordError(this); 
    } 
} 

//Test class 
public class Test { 
    public void test() { 
     //Create an error handler instance. 
     ErrorHandler handler = new LoggingErrorHandler(); 

     try { 
      doSomething();//throws AbstractError 
     } 
     catch (AbstractError e) { 
      e.handle(handler); 
     } 
    } 
} 
4

जावा enums बहुत शक्तिशाली हैं और अनुमति देने के प्रति उदाहरण विधि कार्यान्वयन:

public enum ErrorCode { 
     INVALID_LOGIN { 
     public void handleError() { 
      // do something 
     } 
    }, 
     INVALID_PASSWORD { 
     public void handleError() { 
      // do something else 
     } 
    }, 
     SESSION_EXPIRED { 
     public void handleError() { 
      // do something else again 
     } 
    }; 

    public abstract void handleError(); 
} 

तो फिर तुम बस errorCode.handleError(); कॉल कर सकते हैं। हालांकि, यह संदिग्ध है कि क्या त्रुटि कोड वास्तव में उस तर्क के लिए सही जगह है।

+1

आह, मुझे एहसास नहीं हुआ कि आप एक enum में अमूर्त तरीकों को जोड़ सकते हैं। काफी स्मार्ट – Spoike

+0

अग्रिम धन्यवाद। मुझे लगता है कि इंटरफ़ेस को कार्यान्वित करना है जो कि अन्य इंटरफेस को बढ़ाता है जो बहुत अधिक कोड है। मैं सब हटा देता हूँ। यह दृष्टिकोण बहुत आकर्षक है –

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