2010-03-06 15 views
5

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

मैं ऐसा करने के लिए कुछ विचारों के साथ आया हूं। सबसे पहले बेस श्रेणी बनाने के लिए base_translator कहा जाता है और वर्चुअल विधि (translate()) प्रदान करता है जो प्रत्येक अनुवादकों को ओवरराइड करना पड़ता है। अब एक कारखाना translator_factory बनाएं और भाषा नाम के साथ create() पर कॉल करें। यह कारखाना उपयुक्त उदाहरण वापस करेगा।

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

struct translator 
{ 
    const char* name; 
    void (*fp)(); 
}; 

जो सिर्फ एक भाषा का नाम और एक फ़ंक्शन पॉइंटर रखता है जो इसे संसाधित कर सकता है। उपयोग होगा,

static translator translators[] = { 
    {"first", first}, 
    {"second", second} 
}; 
const char* language = /* */; 
for(int i = 0; i < 2; i++) { 
    translator *t = translators + i; 
    if(strcmp(t->name, language) == 0) { 
     t->fp(); 
     break; 
    } 
} 

यह दृष्टिकोण बनाए रखना बहुत आसान और आसान है। लेकिन मुझे आश्चर्य है, क्या यह समस्या का सबसे अच्छा तरीका है? क्या आपको यह बेहतर बनाने के लिए कोई सुझाव है?

कोई भी मदद महान होगी।

+0

आपका दूसरा दृष्टिकोण केवल सी शैली में सी ++ 'रनटाइम पॉलीमोर्फिज्म (वर्चुअल फ़ंक्शंस) को अनुकरण करता है। सी ++ में ओओपी के अंतर्निहित समर्थन पर इसका कोई लाभ नहीं है। –

उत्तर

3

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

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

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

+0

धन्यवाद। फैक्टरी अधिक समझ में आता है। कारखाने के बारे में पॉलिमॉर्फिक उदाहरण के बजाय फ़ंक्शन पॉइंटर कैसे लौटाता है? –

+0

@Appu मेरा अपडेट देखें। –

+0

उन सभी को मदद के लिए धन्यवाद। मैं वास्तव में इसकी प्रशंसा करता हूँ। –

5

यह आम तौर पर सार वर्गों और आभासी कार्यों के लिए एक धन्य उपयोग-मामला है। तुम क्यों के रूप में "से अधिक इंजीनियरिंग" इसके बारे में लगता है कि मैं मिलता है नहीं .... o_O

बिंदु ताकि आपके कोड को आसानी से एक्स्टेंसिबल है एक अनुबंध को परिभाषित करने के लिए है, और "मुख्य कोड" नहीं है वास्तविक कार्यान्वयन विवरण के बारे में चिंता करने के लिए।

2

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

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