2012-04-28 14 views
7

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

उदाहरण के लिए, नीचे की तरह कुछ, जहां निष्पादित विधि की पसंद एक प्रकार के ऑब्जेक्ट के ऑब्जेक्ट का केवल एक फ़ील्ड निर्भर है।

switch(actor.getTagField()) 
{ 
    case 1: actor.act1(); break; 
    case 2: actor.act2(); break; 
    [...] 
} 

actor.act(); 

बन जाएगा और कार्य विधि अभिनेता के उपवर्गों में अधिरोहित किया जाएगा।

हालांकि, क्रम जो उपवर्ग का दृष्टांत के लिए कम से तय करने के लिए सबसे स्पष्ट रास्ता बहुत मूल के समान दिखता है:

तो यह कुछ भी नहीं की तरह लगता है
Actor newActor(int type) 
{ 
    switch(type) 
    { 
     case 1: return new Actor1(); 
     case 2: return new Actor2(); 
     [...] 
    } 
} 

वास्तव में प्राप्त किया गया है; तर्क अभी ले जाया गया है।

ऐसा करने का बेहतर तरीका क्या है? अभिनेता के प्रत्येक उप-वर्ग के लिए फैक्ट्री क्लास को लागू करने में शामिल होने का एकमात्र तरीका है, लेकिन यह इतनी सरल समस्या के लिए बोझिल लगता है।

क्या मैं इस पर विचार कर रहा हूं? ऐसा लगता है कि मूल परिवर्तन करने का कोई मतलब नहीं है अगर मैं कहीं और भी वही चीज़ करता हूं।

उत्तर

4

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

अन्यथा, आप केवल मूल विरासत को देख रहे हैं। कुछ ..

class Actor{ 
    public void act(){ 
    System.out.println("I act.."); 
    } 
} 

class StuntActor extends Actor { 
    public void act(){ 
    System.out.println("I do fancy stunts.."); 
    } 
} 

class VoiceActor extends Actor { 
    public void act(){ 
    System.out.println("I make funny noises.."); 
    } 
} 

उपयोग करने के लिए, आप केवल उस अभिनेता के प्रकार को तुरंत चालू कर सकते हैं जिसकी आपको आवश्यकता है।

Actor fred = new Actor(); 
Actor tom = new VoiceActor(); 
Actor sally = new StuntActor(); 

fred.act(); 
tom.act(); 
sally.act(); 

आउटपुट:

I act.. 
I make funny noises.. 
I do fancy stunts.. 

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

आप Actors..aka विज़ एक फैक्टरी के निर्माण को केंद्रीकृत करने की जरूरत है, तो आप से दूर होने में सक्षम नहीं होगा कुछ प्रकार के स्विचिंग तर्क - किस मामले में ..मैं आम तौर पर पठनीयता के लिए एक गणना का उपयोग करेंगे:

public class Actor{ 
    public enum Type{ REGULAR, VOICE, STUNT } 

    public static Actor Create(Actor.Type type){ 
    switch(type) { 
     case VOICE: 
     return new VoiceActor(); 
     case STUNT: 
     return new StuntActor(); 
     case REGULAR: 
     default: 
     return new Actor(); 
    } 
    } 

    public void act(){ 
    System.out.println("I act.."); 
    } 
} 

उपयोग:

Actor some_actor = Actor.Create(Actor.Type.VOICE); 
some_actor.act(); 

आउटपुट:

I make funny noises.. 
+0

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

+0

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

+0

आप जो कर रहे हैं वह अभिनेताओं के निर्माण को केंद्रीकृत करने के लिए "निर्णय लेना" है। आप चाहते हैं कि अभिनेता एक ही स्थान से आ रहे हों, इस मामले में .. आप स्विचिंग के आसपास नहीं जा सकते ... क्योंकि यह एक निर्णय है अंतिम उपयोगकर्ता। –

1

मुझे विश्वास है कि आप इसे Abstract factory pattern के साथ क्या कर सकते हैं ...

यह एक उदाहरण है:

abstract class Computer { 
    public abstract Parts getRAM(); 
    public abstract Parts getProcessor(); 
    public abstract Parts getMonitor(); 
} 

class Parts { 
    public String specification; 
    public Parts(String specification) { 
     this.specification = specification; 
    } 
    public String getSpecification() { 
     return specification; 
    } 
} 

हम दो वर्ग है कि Computer

class PC extends Computer { 
    public Parts getRAM() { 
     return new Parts("512 MB"); 
    } 
    public Parts getProcessor() { 
     return new Parts("Celeron"); 
    } 
    public Parts getMonitor() { 
     return new Parts("15 inches"); 
    } 
} 

class Workstation extends Computer { 
    public Parts getRAM() { 
     return new Parts("1 GB"); 
    } 
    public Parts getProcessor() { 
     return new Parts("Intel P 3"); 
    } 
    public Parts getMonitor() { 
     return new Parts("19 inches"); 
    } 
} 

फैली और अंत में हमारे पास ,

public class ComputerType { 
    private Computer comp; 
    public static void main(String[] args) { 
     ComputerType type = new ComputerType(); 
     Computer computer = type.getComputer("Workstation"); 
     System.out.println("Monitor: "+computer.getMonitor().getSpecification()); 
     System.out.println("RAM: "+computer.getRAM().getSpecification()); 
     System.out.println("Processor: "+computer.getProcessor().getSpecification()); 
    }  

    public Computer getComputer(String computerType) { 
     if (computerType.equals("PC")) 
      comp = new PC(); 
     else if(computerType.equals("Workstation")) 
      comp = new Workstation(); 
     return comp; 
    }  
} 
+0

मैंने इसे पहले देखा था, लेकिन मैंने सोचा कि शायद यह संभवतः अनावश्यक रूप से जटिल था जो मैं करना चाहता था। मुझे यकीन नहीं है। – flowsnake

2

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

यह दो चीजें करता है, इससे पहले यह एक कारखाने और के अंदर एक स्विच में कई स्विच को कम कर देता है, यह एक साथ खींचता है जो संभवतः समान डेटा पर निर्भर करता है। वह डेटा आपकी ऑब्जेक्ट्स में सदस्य चर में बदल जाएगा।

यह भी ध्यान देने योग्य है कि आप हमेशा अपने कारखाने के हुड के नीचे स्विच स्टेटमेंट के साथ समाप्त नहीं होते हैं। हो सकता है कि आप स्टार्टअप पर क्लासपाथ स्कैन कर सकें और इंटरफेस को लागू करने वाले HashMap प्रकारों का निर्माण कर सकें। उदाहरण के लिए, एसएमटीपी जैसे सॉकेट प्रोटोकॉल के कार्यान्वयन पर विचार करें। आपके पास HeloCommand, MailFromCommand, आदि नाम की ऑब्जेक्ट हो सकती हैं ... और वर्ग नाम पर सॉकेट कमांड से मेल करके संदेश को संभालने के लिए सही ऑब्जेक्ट पाएं।

+0

मैंने वास्तव में ऐसा कुछ करने पर विचार किया, लेकिन फिर इस बारे में पढ़ना शुरू किया कि प्रतिबिंब अंतिम उपाय होना चाहिए। – flowsnake

+0

प्रतिबिंब एक शक्तिशाली उपकरण है और प्रदर्शन का त्याग किए बिना इसका उपयोग करने के तरीके हैं। मेरे उत्तर में वर्णित उदाहरण केवल एक बार शुरू होने पर प्रतिबिंब का उपयोग करेगा और उसके बाद 'हैश मैप' का उपयोग करेगा। –

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