2013-09-30 6 views
5

वर्तमान में हमारे पास दो ग्राहक कोड "कस्टा" और "सीएसटीबी" हैं। कस्टा ऑपरेशन ए 1, ए 2, ए 3, ए 4, ए 5, ए 6 कर सकते हैं। सीएसटीबी कुछ स्थितियों के आधार पर संचालन बी 1, बी 2, बी 3, बी 4, बी 5, बी 6 कर सकता है। वर्तमान में वे किसी और ग्राहक कोड की अपेक्षा नहीं कर रहे हैं, लेकिन मैं डिज़ाइन लचीला होना चाहता हूं। इन्हें डेटाबेस में संग्रहीत किया जा सकता है लेकिन जैसा कि मैंने उल्लेख किया है क्योंकि यह किसी अन्य ग्राहक कोड के लिए लंबे समय तक होने की संभावना नहीं है, इसे कोड में प्रदर्शित करने की आवश्यकता है।जावा एनम या अन्य संग्रह

आवेदन तर्क बुनियादी एल्गोरिथ्म लग रहा है

तरह
if ConditionX is true 
then if customerCode is "CUSTA" 
    then applicableOperation = 'A1' 
    else 
     if customerCode is "CUSTB" 
     then applicableOperation = 'B1' 
     end 
else 
    if ConditionY is true  
    then 
     if customerCode is "CUSTA" 
     then applicableOperation = 'A2' 
     else 
      if customerCode is "CUSTB" 
       then applicableOperation = 'B2' 
      end 
     else 

............... ................

मैं स्विच स्टेटमेंट इत्यादि लिख सकता हूं। एल्गोरिदम को साफ करने के लिए, लेकिन मेरी मुख्य चिंता यह है कि "कस्टा", "सीएसटीबी", "ए 1", "ए 2", "ए 3", "ए 4" का प्रतिनिधित्व कैसे किया जाए। .. "ए 6", "बी 1", "बी 2" ... "बी -6"। ग्राहक कोड enum

तरह
public enum CustomerCode { CUSTA, CUSTB } 
public enum OperationsForA{ A1, A2, A3,...A6 } 
public enum OperationsForB{ B1, B2, B3...B6} 

मैं एक Map निर्मित नहीं करेगी जहां कुंजी CustomerCode है और मूल्यों के रूप में संबंधित संचालन जोड़ने होना है।

इस समस्या को हल करने का सबसे अच्छा समाधान क्या होगा। इसके अलावा, भविष्य में, उदाहरण के लिए, "सीएनटीसी" जोड़ने के लिए लचीला होना चाहिए।

धन्यवाद

उत्तर

0

मैं पूरी बात एक डेटाबेस में एक लुकअप तालिका बनाने के लिए, और यथासंभव कम कोड लिखेंगे। यह बदल सकता है या नहीं भी हो सकता है, लेकिन अगर ऐसा नहीं होता है तो यह तालिका के रूप में सभी को और अधिक समझ देगा।

+0

मैं सहमत हूं .. लेकिन मैं जावा में विकल्पों की तलाश में हूं। –

+0

यदि आप वास्तव में सहमत हैं, * आप जावा में विकल्प क्यों ढूंढ रहे हैं? – EJP

0

मान लिया जाये कि A1 बी 1, आदि के समान है, मैं इसे इस तरह लागू करेगा और उन्हें एक ही आपरेशन नाम देने:

public enum Customer { 
    CUSTA, CUSTB; 

    public void operation1(){ 
     switch(this){ 
     case CUSTA: 
      // do A thing; 
      break; 
     case CUSTB: 
      // do it the B way 
      break; 
     } 
    } 
} 

तुम क्या कोशिश कर रहे हैं में है कि फिट करने के लिए कर सकता है?

बेशक यदि आप एक एनम का उपयोग करने जा रहे हैं तो आपको नया ग्राहक प्रकार मिलने पर कोड अपडेट करना होगा, लेकिन आपको शायद कोड को अपडेट करना होगा। एक अन्य और संभवतः बेहतर दृष्टिकोण एक इंटरफ़ेस को परिभाषित करना और फैक्टरी पैटर्न का उपयोग करना है; इसे बाहर क्लीनर आ सकते हैं:

public interface Customer { 
    void operation1(); 
} 

class CustomerFactory{ 
    public static Customer getByName(String cust){ 
     if(cust.equals("CUSTA")){ 
      return new CustomerA(); 
     } 
     if(cust.equals("CUSTB")){ 
      return new CustomerB(); 
     } 
     throw new IllegalArgumentException(
       "Customer type " + cust + " not supported."); 
    } 
} 

class CustomerA implements Customer{ 
    @Override 
    public void operation1(){ 
     /* A's implementation */ 
    } 
} 

class CustomerB implements Customer{ 
    @Override 
    public void operation1(){ 
     /* B's implementation */ 
    } 
} 

एक आखिरी बात मैं जोड़ना होगा कि आप ग्राहक के कार्यान्वयन है कि कोई कोड के साथ लोड होगा जोड़ने होगा जब तक वे अपने classpath पर हैं बदलता है प्रतिबिंब का उपयोग करें और कक्षा में पारित करने के लिए है फैक्टरी के नाम:

package test; 

import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationTargetException; 

public class CustomerTest{ 
    public static void main(String[] arg){ 
     CustomerFactory.getByName("test.CustomerA").operation1(); 
     CustomerFactory.getByName("test.CustomerB").operation1(); 
     CustomerFactory.getByName("test.CustomerC").operation1(); 
    } 
} 
interface Customer { 
    void operation1(); 
} 

class CustomerFactory{ 
    public static Customer getByName(final String cust){ 
     try{ 
      Class<? extends Customer> customerSubclass 
       = Class.forName(cust).asSubclass(Customer.class); 

      Constructor<? extends Customer> constructor 
       = customerSubclass.getDeclaredConstructor(new Class[0]); 

      return constructor.newInstance(new Object[0]); 
     } catch(ClassNotFoundException e){ 
      System.err.println("Trouble finding .class file for class "+cust+". "+e); 
     } catch(ClassCastException e){ 
      System.err.println("Found .class file for "+cust+" but it doesn't implement Customer."+" "+e); 
     } catch(NoSuchMethodException e){ 
      System.err.println("Class "+cust+" doesn't provide a no-arg constructor. :("+" "+e); 
     } catch(IllegalAccessException e){ 
      System.err.println("No-arg constructor isn't accessible. :("+" "+e); 
     } catch(InstantiationException e){ 
      System.err.println("Couldn't instantiate?"+" "+e); 
     } catch(InvocationTargetException e){ 
      System.err.println("Umm... something else broke."+" "+e); 
     } 
     throw new IllegalArgumentException(
       "Customer type " + cust + " not supported."); 
    } 
} 

class CustomerA implements Customer{ 
    @Override 
    public void operation1(){ 
     /* A's implementation */ 
     System.out.println("I'm an A doing operation1!"); 
    } 
} 

class CustomerB implements Customer{ 
    @Override 
    public void operation1(){ 
     /* B's implementation */ 
     System.out.println("I'm a B doing operation1!"); 
    } 
} 
+1

पहले दृष्टिकोण के लिए, शीर्ष स्तर पर एक सार विधि के रूप में 'ऑपरेशन 1' घोषित करने के लिए बेहतर है और फिर प्रत्येक enum स्थिरता के लिए विधि को लागू करें। –

+0

यह एक बुरा विचार नहीं है, लेकिन यह भी इस बात पर निर्भर करता है कि कार्यान्वयन कितने समान या अलग हैं। अधिक जानकारी के बिना यह जानना मुश्किल है कि कौन सा दृष्टिकोण लेना है। +1 हालांकि। – UFL1138

4

A1 बी 1 से मेल खाती है, तो ए 2 बी 2 से मेल खाती है, और इतने पर है, तो आप polymorphism की जरूरत है।

इसका मतलब है कि आपके पास एक सामान्य CustomerOperations इंटरफ़ेस होगा। प्रत्येक ग्राहक कोड CustomerOperations इंटरफ़ेस का ठोस कार्यान्वयन करेगा और Condition X, Condition Y इत्यादि के लिए सही ऑपरेशन कोरसेपेंडिंग लौटाएगा।इंटरफेस

interface CustomerOperations { 
    Operation operationForX(); 
    Operation operationForY(); 
} 

interface Operation { 
    Result someMethod(); 
} 

अपने enums सेट करें और लागू:

enum OperationsForA implements Operation { 
    A1, A2, A3; 
    // Implement someMethod 
} 

enum OperationsForB implements Operation { 
    B1, B2, B3; 
    // Implement someMethod 
} 

enum CustomerCode implements CustomerOperations { 
    CUSTA { 
    Operation operationForX() { 
     return OperationsForA.A1; 
    } 
    Operation operationForY() { 
     return OperationsForA.A2; 
    } 
    }, 

    CUSTB { 
    Operation operationForX() { 
     return OperationsForB.B1; 
    } 
    Operation operationForY() { 
     return OperationsForB.B2; 
    } 
    } 
    ; 
} 

उदाहरण उपयोग: (यह वह जगह है जहाँ बहुरूपता होता है)

अपने इंटरफेस सेट करें

public class Main { public static void main(String... args) { CustomerOperations operator = CustomerOperations.CUSTA; if (conditionX) { // Could be inlined, but I've separated it for type readability: // Get the appropriate operation from the operator. Operation thingToDoForX = operator.operationForX(); // Run the operation and get the result Result result = thingToDoForX.someMethod(); } } } 
+0

+1 यह लचीलापन की सही मात्रा है। मैंने अतीत में डिज़ाइन देखा है जो अत्यधिक जटिल हैं क्योंकि वे कभी भी होने वाले परिवर्तनों को अनुकूलित करने के लिए लचीलापन के लिए प्रयास करते हैं। जावा में इस तर्क को रखने से यह बदलना आसान हो जाता है, लेकिन अगर यह नहीं बदलता है तो बहुत कम खो जाता है। – Brandon

1

enum के बाद से मूल्यों, जावा में वर्ग हैं आप कुछ इस तरह कर सकते हैं:

CustomerCode customerCode = . . .; 
if (conditionX()} { 
    customerCode.op1(); 
} else if (conditionY()) { 
    customerCode.op2(); 
} // etc. 

यह वास्तुकला समझ में आता है, तो आप के लिए कदम सकता है:

public enum CustomerCode { 
    CUSTA { 
     @Override 
     public void op1() { 
      // operation A1 implementation 
     } 
     @Override 
     public void op2() { 
      // operation A2 implementation 
     } 
     // etc. 
    }, 
    CUSTB { 
     @Override 
     public void op1() { 
      // operation B1 implementation 
     } 
     // etc. 
    }; 
    public abstract void op1(); 
    public abstract void op2(); 
    // etc. 
} 

फिर अपने आवेदन तर्क दिखाई दे सकता है Enum कोड के अंदर if...else श्रृंखला; इस मामले में आपको केवल एक ही विधि की आवश्यकता हो सकती है: doApplicableOperation()

एक बहुत ही अलग दृष्टिकोण एक इंटरफेस (जैसे, Runnable या Callable) के रूप में संचालन को परिभाषित करने और इंटरफेस के उदाहरण के लिए CustomerCode से एक EnumMap के लिए किया जाएगा। (प्रत्येक ऑपरेशन के लिए EnumMap हो सकता है।)

0

एनम कोई अच्छा नहीं है, क्योंकि एनम के सभी उदाहरणों में समान विधियां होनी चाहिए।

यहां तक ​​कि प्रकार के लिए एक enum का उपयोग करना शायद गलत लगता है, क्योंकि आप प्रभावी ढंग से उदाहरण कर रहे हैं, जो आम तौर पर एक डिजाइन गंध है।

मुझे लगता है कि आप विरासत का एक क्लासिक मामले मिल गया है: आधार वर्ग में एक आम सार व्यवहार करने के लिए सार अपने तरीकों के

public abstract class Customer { 
    // common code 
} 
public class CustomerA extends Customer { 
    // specific/decorated behaviour 
} 
public class CustomerB extends Customer { 
    // specific/decorated behaviour 
} 

प्रयास करें।

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