2013-01-10 16 views
5

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

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

   |----- | 'HOME' 
       |Place?| ----- > *destination = 'home'* 
       |----- | 
    Zoo A   |        Zoo B 
    |---------------|----------------------------------------| 
|----------|          |----------| 
|Direction?|          |Direction?| 
|----------|          |----------| 
    | North           | North 
    ----------- *destination = 'Zoo A North'   ----------- *destination = 'Zoo B North' 
    | East           | East 
    ----------- *destination = 'Zoo A East'    ----------- *destination = 'Zoo B East' 
    | South           | South 
    ----------- *destination = 'Zoo A South'   ----------- *destination = 'Zoo B South' 
    | West           | West 
    ----------- *destination = 'Zoo A West'    ----------- *destination = 'Zoo B West' 

तो व्यक्ति एक्स चिड़ियाघर एक की जगह और दक्षिण की एक दिशा है, तो वे की एक गंतव्य होना चाहिए 'चिड़ियाघर एक दक्षिण'

मैं कोड है कि वर्तमान में बहुत बदसूरत है का उपयोग कर यदि बयान:

if(Place = 'HOME') 
    destination = 'HOME' 
if(Place = 'Zoo A') 
    if(Direction = North) 
     destination = 'Zoo A North') 
    if(Direct = East) 
     destination = 'Zoo A East') 
    ... 
if(Place = 'Zoo B') 
    if(Direction = North) 
     destination = 'Zoo B North') 
    if(Direct = East) 
     destination = 'Zoo B East') 
    ... 

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

कैसे तर्क से निपटने के लिए पर कोई सुझाव इस तरह बहती है? धन्यवाद

+0

मैं आपके उदाहरण में जो करने की कोशिश कर रहा हूं उस पर पूरी तरह स्पष्ट नहीं हूं। क्या "प्लेस" और "डायरेक्शन" स्ट्रिंग्स या किसी अन्य प्रकार की वस्तुएं हैं? किसी भी तरह से, आपके 'चिड़ियाघर' वर्ग में 'goNorth() ', आदि विधियों को बनाने का एक सरल उदाहरण हो सकता है। मुझे पूरी तरह से यकीन नहीं है कि यह आपकी समस्या का समाधान करेगा, हालांकि, क्योंकि आप जो करने की कोशिश कर रहे हैं उस पर मैं पूरी तरह से स्पष्ट नहीं हूं। –

+0

@ कोड-गुरु - मान लें कि वे सादगी के लिए सभी तार हैं। मैं जो करने की कोशिश कर रहा हूं वह प्रवाह के शीर्ष पर शुरू होता है और चर (दिशा और स्थान) के आधार पर अंतिम 'गंतव्य' के साथ समाप्त होता है। लेकिन सबसे प्रबंधनीय और आसान बनाए रखने के तरीके में – NathanS

उत्तर

3

यह इस तरह तैयार किया जा सकता है, जबकि का उपयोग करके देखें :

  1. विधि calculateDestination(Person) विधि के साथ रूट क्लास Place का उपयोग करें। जगह के अंदर अन्य स्थानों को शामिल किया जा सकता है।
  2. PlaceZoo और ZooQuadrant के लिए उप-वर्ग बनाएं (स्वाभाविक रूप से, क्योंकि ये वास्तविक स्थान हैं)।
  3. Person वस्तु के लिए currentPlace और currentDirection

अब आप अपनी स्थिति को दर्शाने के लिए इन कक्षाओं की वस्तुओं का दृष्टांत था मान हैं:

zooA = new Zoo("ZooA"); 
zooA.addChild(new ZooQuadrant(Direction.SOUTH)); 
... so on for every quadrant ... 
... same for zooB ... 
home = new Place("Home"); 
world = new Place("World"); 
world.addChild(home); 
world.addChild(zooA); 
world.addChild(zooB); 

आप गंतव्य प्राप्त करना चाहते हैं, तो आप कहेंगे world.calculateDestination(myPerson)

calculateDestination(Person) पॉलिमॉर्फिक विधि है। विरासत पदानुक्रम में प्रत्येक स्तर उस वर्ग के विशिष्ट अर्थशास्त्र के अनुसार इसे ओवरराइड करेगा।

  1. Place एक सामान्य कार्यान्वयन अगर Person उदाहरण उस नोड (currentPlace के लिए Person के मूल्य के खिलाफ परीक्षण द्वारा) पर वर्तमान में है कि परीक्षण किया जाएगा और यदि नहीं, वह अपने बच्चों में से प्रत्येक के और पर calculateDestination फोन होगा उसे वापस करो।
  2. Zoo एस को currentPlace == this की जांच करने की आवश्यकता होगी, और यदि ऐसा है, तो अपने प्रत्येक क्वाड्रंट पर calculateDestination पर कॉल करें और this.name + quadrantResult लौटने के लिए अपने सकारात्मक परिणाम को गठबंधन करें।
  3. प्रत्येक ZooQuadrant सिर्फ यह जांचने की आवश्यकता है कि currentDirection अपनी दिशा के बराबर है, और उसके अनुसार एक मूल्य वापस करें।

नोट: यह सिर्फ यह स्पष्ट करने के लिए है कि बहुरूपता कैसे काम कर सकती है, बेहतर कार्यान्वयन हो सकते हैं। इसके अलावा, यहां हम बहुरूपता और रिकर्सन दोनों का उपयोग कर रहे हैं, दोनों स्वतंत्र हैं।


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

कि क्या के रूप में जटिलता न्यायसंगत न हो, कि निर्भर करता है! यहां हम ऑब्जेक्ट ग्राफ के साथ एक साधारण उदाहरण के साथ काम कर रहे हैं जो काफी छोटा है। जैसे ही आपके पास ज़ूज़ हैं, उन्हें उन चिड़ियाघर में और अधिक चतुर्भुज जोड़ना होगा, या निर्णय के अतिरिक्त स्तरों को बनाने की आवश्यकता है (उदाहरण के लिए प्रत्येक चतुर्भुज के पास subquadrants है), नेस्टेड अगर-else-if विधि (प्रक्रियात्मक) वास्तव में हो जाता है बालों वास्तव में जल्दी, जबकि वस्तु उन्मुख दृष्टिकोण बनाए रखने योग्य और समझ में आता है।

सबकुछ की तरह, यदि आप भविष्य में यह निर्णय ले रहे हैं कि निर्णय जटिल हो जाएंगे, तो ओओ दृष्टिकोण के साथ जाएं। अन्यथा, इसे सरल ट्रम्प सौंदर्य हर बार रखते हुए: सही समस्याओं के लिए सही टूल का उपयोग करें।

+0

सुझाव के लिए धन्यवाद, मैंने इसका एक कामकाजी मॉडल बनाया है (यह पोस्ट करने में बहुत लंबा है :()। इसे देखकर मुझे लगता है कि मैं बस जो कर रहा हूं उसे जटिल करने की कोशिश कर रहा हूं। यह अच्छा काम करता है! हम्म .. – NathanS

0

एक दृष्टिकोण यह है कि आप एक विधि प्राप्त करने के साथ माता-पिता एस्बट्रैक्ट क्लास/इंटरफ़ेस 'प्लेस' बना सकते हैं। नॉर्थडिस्टिनेशन(), getEastDestination() और इसी तरह।

तो फिर तुम 'स्थान' 'ZooA' और 'Zoob' कहा जाता है की एक उपवर्ग/कार्यान्वयन बनाते हैं, और ओवरराइड/getXXXDestination() विधि को लागू इसी स्थान

+0

बनाए रखने के लिए और अधिक काम होगा, दिशा जोड़ने के लिए दक्षिणएस्ट, ऊपर, नीचे आप कई जगहों पर विधियों को जोड़ने के लिए हवादार हो जाएंगे। – BevynQ

+0

यही वह है जिसे मैं टालना चाहता हूं, भविष्य में बदलाव जो एक नया चिड़ियाघर जोड़ सकता है, या एक नई दिशा जो तर्क को तोड़ नहीं सकती है। @gerrytan - यह एक अच्छा विचार है, अगर यह ब्लॉक को 'if (प्लेस प्लेस = चिड़ियाघर ए) रिटर्न प्लेस = नया चिड़ियाघर ए' को सीमित कर देगा ... तो बस दिशा पर एक स्विच कॉल करें, 'मामला उत्तर: place.goNorth(); '। क्या वह सही है? – NathanS

0

इस से मैं कम से कम तीन आप वर्गों को देखने के वापस जाने के लिए जगह, दिशा और गंतव्य होना चाहते हैं।

प्लेस एक नाम संपत्ति और एक getName() विधि नाम चिड़ियाघर एक करने के लिए स्थापित किया जा रहा, चिड़ियाघर बी, घर के लिए होगा।

आप घर और चिड़ियाघर प्लेस के उपवर्गों होगा अगर वे अलग व्यवहार कर। इस उदाहरण में आप ऐसा कर सकते हैं क्योंकि घर की कोई दिशा नहीं है लेकिन चिड़ियाघर करता है।

दिशा एक एनम (जो कि केवल एक विशेष प्रकार की कक्षा है) हो सकती है जिसमें उत्तर, पूर्व, पश्चिम, दक्षिण शामिल है।

गंतव्य दो गुण प्लेस और दिशा जा रहा होगा। इसमें एक विधि भी होगी()

public String getDestination(){ 
    if (this.direction == null){ 
     result = this.place.getName(); 
    } else { 
     result = this.place.getName() + " " + this.direction.getName(); 
    } 
    return result; 
} 
0

गैरीटन के उत्तर के साथ जाएं। जानकारी के हर टुकड़े के लिए, आपको खुद से पूछना चाहिए, "क्या मुझे इसके लिए वास्तव में कक्षा चाहिए?"। कई बार, जवाब नहीं है। सरल स्ट्रिंग/संख्यात्मक चर पर्याप्त है।अब, आप गेटटर/सेटर विधियों के साथ इन चर को जोड़ना चाहते हैं, क्योंकि यह जावा जनता पर जोर देता है, क्योंकि सार्वजनिक चर को सीधे संदर्भित करने के विपरीत (जैसे सी ++)। उदाहरण के लिए परीक्षण की तुलना में सरल तरीकों का संदर्भ देना बहुत आसान है।

0

आप इसे में चिड़ियाघर एक और चिड़ियाघर बी के साथ एक नई पद्धति बना सकते हैं ...... आप इसे directionForZoo() की तरह कॉल कर सकते हैं, और यदि छोरों

0

यदि आप इसे इंजीनियर नहीं करना चाहते हैं, तो निम्नलिखित कार्यवाही अगर/अन्य से छुटकारा पाने के लिए एक आसान समाधान होगा। लेकिन यह एक सुरुचिपूर्ण दृष्टिकोण नहीं है।

आपके पास एक नक्शा हो सकता है जिसमें कुंजी हैं (प्लेस + दिशा) और मान संबंधित गंतव्यों हैं। यह ठीक है अगर आपके कार्यक्रम में इस समय स्थान और दिशा मान अधिक स्थिर हैं और यह अधिक परिवर्तन करने की संभावना नहीं है।

उदाहरण के लिए: प्लेस और दिशा के अनुसार अपने स्थानों भंडारण और एक नक्शा

Map<String, String> destMap = new HashMap<String, String>(); 
destMap.put("HOME","HOME"); 
destMap.put("Zoo A+North","Zoo A North"); 
destMap.put("Zoo A+East","Zoo A East"); 
destMap.put("Zoo B+North","Zoo B North"); 

में इसी गंतव्य गंतव्य प्राप्त कर रहा है:

destMap.get(Place + "+" + Direction); 
0

अपने उदाहरण के लिए एक संभव समाधान एक बनाने के लिए है (संभवतः सार) Location कक्षा। इसमें आपके गंतव्यों के लिए डेटा संरचना हो सकती है। इस डेटा संरचना के लिए एक संभावना शायद एक Map<Direction, Location> है) जहां Direction एक enum है जिसका उपयोग उस कुंजी के रूप में किया जा सकता है जो Location ऑब्जेक्ट को मानचित्र करता है जो उस दिशा के लिए गंतव्य है। Home, Zoo, आदि वर्ग बनाने के लिए आप या तो Location उप-वर्ग बना सकते हैं या आप name फ़ील्ड प्रदान कर सकते हैं जो विभिन्न Location एस को अलग करता है। या आप इनमें से दोनों का कुछ संयोजन कर सकते हैं।

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

0

मैंने कुछ सुझाए गए उत्तरों पर एक बदलाव की कोशिश की।

मैं एक नेस्टेड स्विच केस ब्लॉक का उपयोग कर समाप्त हुआ। सबसे आदर्श नहीं है और मैं इससे बचना चाहता था लेकिन मेरे उद्देश्यों के लिए यह अधिक रखरखाव योग्य है (यह बदलने या विस्तारित नहीं होने वाला है)।

मैं @Ezequiel Muns विधि को सही के रूप में चिह्नित करने जा रहा हूं क्योंकि इस के मेरे संस्करण ने बहुत अच्छी तरह से काम किया - इसकी समस्या के लिए इसकी आवश्यकता नहीं है।

सभी मदद के लिए धन्यवाद।

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