क्या मुझे इस परिदृश्य में रचना या विरासत पसंद करनी चाहिए?


11

एक इंटरफ़ेस पर विचार करें:

interface IWaveGenerator
{
    SoundWave GenerateWave(double frequency, double lengthInSeconds);
}

यह इंटरफ़ेस कई वर्गों द्वारा कार्यान्वित किया जाता है जो विभिन्न आकृतियों की तरंगें उत्पन्न करते हैं (उदाहरण के लिए, SineWaveGeneratorऔर SquareWaveGenerator)।

मैं एक वर्ग को लागू करना चाहता हूं जो SoundWaveसंगीत डेटा के आधार पर उत्पन्न होता है , न कि कच्चे ध्वनि डेटा पर। यह एक नोट का नाम और बीट्स (सेकंड नहीं) के संदर्भ में एक लंबाई प्राप्त करेगा, और आंतरिक रूप IWaveGeneratorसे एक SoundWaveतदनुसार बनाने के लिए कार्यक्षमता का उपयोग करेगा ।

सवाल यह है कि क्या इसे लागू किया जाना चाहिए या NoteGeneratorइसमें कोई IWaveGeneratorउत्तराधिकार होना चाहिए IWaveGenerator?

मैं दो कारणों से रचना की ओर झुक रहा हूं:

1- यह मुझे किसी भी इंजेक्षन करने की अनुमति देता IWaveGeneratorकरने के लिए NoteGeneratorगतिशील रूप से। इसके अलावा, मैं केवल एक की जरूरत है NoteGeneratorवर्ग, के बजाय SineNoteGenerator, SquareNoteGeneratorआदि

2- NoteGeneratorद्वारा परिभाषित निचले-स्तर के इंटरफ़ेस को उजागर करने की कोई आवश्यकता नहीं है IWaveGenerator

हालाँकि मैं इस बारे में अन्य राय सुनने के लिए इस सवाल को पोस्ट कर रहा हूं, शायद उन बिंदुओं के बारे में जो मैंने नहीं सोचा था।

BTW: मैं कहूंगा कि NoteGenerator यह वैचारिक रूप से है IWaveGeneratorक्योंकि यह SoundWaveएस उत्पन्न करता है ।

जवाबों:


14

यह मुझे गतिशील रूप से NoteGenerator में किसी IWaveGenerator को इंजेक्ट करने की अनुमति देता है। इसके अलावा, मुझे SineNoteGenerator , SquareNoteGenerator , इत्यादि के बजाय केवल एक NoteGenerator वर्ग की आवश्यकता है ।

यही कारण है कि एक स्पष्ट संकेत इसे यहाँ उपयोग संरचना के लिए बेहतर होगा है, और से विरासत में नहीं SineGeneratorया SquareGenerator(बदतर) दोनों या। फिर भी, IWaveGeneratorयदि आप उत्तरार्द्ध को थोड़ा बदल देते हैं, तो सीधे नोटगेंसर को इनहेरिट करना समझ में आएगा ।

यहाँ वास्तविक समस्या यह है कि, शायद NoteGeneratorएक विधि के साथ ऐसा करना सार्थक है

SoundWave GenerateWave(string noteName, double noOfBeats, IWaveGenerator waveGenerator);

लेकिन एक विधि के साथ नहीं

SoundWave GenerateWave(double frequency, double lengthInSeconds);

क्योंकि यह इंटरफ़ेस बहुत विशिष्ट है। आप चाहते हैं IWaveGeneratorजिन वस्तुओं पर उत्पन्न होने की रों SoundWaveरों है, लेकिन वर्तमान में आपके इंटरफ़ेस व्यक्त IWaveGeneratorरों जिन वस्तुओं पर उत्पन्न कर रहे हैं SoundWaveरों आवृत्ति और लंबाई विशेष रूप से । तो बेहतर इस तरह के एक इंटरफेस डिजाइन

interface IWaveGenerator
{
    SoundWave GenerateWave();
}

और , या, या जो भी अन्य जनरेटर आपके दिमाग में है , के निर्माणकर्ताओं के माध्यम से मापदंडों की तरह frequencyया lengthInSecondsया पूरी तरह से अलग सेट पास करें। यह आपको पूरी तरह से अलग निर्माण मापदंडों के साथ अन्य प्रकार के एस बनाने की अनुमति देगा । हो सकता है कि आप एक आयत तरंग जनरेटर जोड़ना चाहते हैं जिसके लिए एक आवृत्ति और दो लंबाई मापदंडों की आवश्यकता होती है, या ऐसा ही कुछ, हो सकता है कि आप आगे एक त्रिकोण तरंग जनरेटर जोड़ना चाहते हैं, वह भी कम से कम तीन मापदंडों के साथ। या, एक , निर्माता मानकों के साथ , , और ।SineWaveGeneratorSquareGeneratorIWaveGeneratorNoteGeneratornoteNamenoOfBeatswaveGenerator

इसलिए यहां सामान्य समाधान आउटपुट फ़ंक्शन से इनपुट मापदंडों को अलग करना है, और इंटरफ़ेस का केवल आउटपुट फ़ंक्शन हिस्सा बनाना है।


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

2
@AvivCohn: "कोड को वास्तव में यह जानना होगा कि यह किस प्रकार का व्यवहार कर रहा है" - नहीं, यह एक गलत धारणा है। केवल उस कोड का हिस्सा जो विशिष्ट प्रकार के जनरेटर (mybe a factory) का निर्माण करता है, और उसे हमेशा यह जानना होता है कि वह किस प्रकार के साथ काम कर रहा है।
डॉक्टर ब्राउन

... और अगर आपको अपनी वस्तुओं के निर्माण की प्रक्रिया को बहुरूपी बनाने की आवश्यकता है, तो आप "एब्सट्रैक्ट फ़ैक्टरी" पैटर्न ( en.wikipedia.org/wiki/Abstract_factory_pattern )
डॉक्टर ब्राउन

यह वह उपाय है जो मैं चुनूंगा। छोटी, अपरिवर्तनीय कक्षाएं यहाँ जाने का सही तरीका है।
स्टीफन

9

NoteGenerator "वैचारिक" है या नहीं, IWaveGenerator कोई मायने नहीं रखता।

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

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


वास्तव में मेरा मतलब यह नहीं था कि मैं इसे NoteGeneratorलागू करूं GenerateWaveबल्कि मापदंडों की अलग तरह से व्याख्या करूं, हां मैं मानता हूं कि यह एक भयानक विचार होगा। मेरा मतलब था कि नोट जेनरेटर एक लहर जनरेटर की विशेषज्ञता की तरह है: यह सिर्फ कच्चे ध्वनि डेटा (उदाहरण के लिए एक आवृत्ति के बजाय एक नोट नाम) के बजाय 'उच्च स्तर' इनपुट डेटा में लेने में सक्षम है। Ie sineWaveGenerator.generate(440) == noteGenerator.generate("a4")। तो सवाल, रचना या विरासत आती है।
अवीव कोहन

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

@Ixrec: वास्तव में, सभी प्रकार के जनरेटर के लिए एक ही इंटरफ़ेस रखना बहुत मुश्किल नहीं है, ओपी को शायद दोनों करना चाहिए, निम्न स्तर के जनरेटर को इंजेक्ट करने के लिए संरचना का उपयोग करें और एक सरलीकृत इंटरफ़ेस से विरासत में मिला (लेकिन नोटगेटर को इनहेरिट नहीं करना चाहिए निम्न स्तरीय जनरेटर कार्यान्वयन) मेरा उत्तर देखें।
डॉक्टर ब्राउन

5

2- IWaveGenerator द्वारा परिभाषित निचले-स्तर के इंटरफ़ेस को उजागर करने के लिए NoteGenerator की कोई आवश्यकता नहीं है।

लगता है जैसे NoteGeneratorएक नहीं है WaveGenerator, इसलिए इसलिए इंटरफ़ेस को लागू नहीं करना चाहिए।

रचना सही विकल्प है।


मैं कहूंगा कि NoteGenerator यह वैचारिक रूप से है IWaveGeneratorक्योंकि यह SoundWaveएस उत्पन्न करता है ।
अवीव कोहन

1
खैर, अगर यह उजागर करने की जरूरत नहीं है GenerateWave, तो यह एक नहीं है IWaveGenerator। लेकिन ऐसा लगता है कि यह एक IWaveGenerator (शायद अधिक?) का उपयोग करता है, इसलिए रचना।
एरिक किंग

@EricKing: यह एक सही उत्तर है जब तक कि किसी को GenerateWaveफ़ंक्शन से चिपकना है क्योंकि यह प्रश्न में लिखा गया है। लेकिन ऊपर की टिप्पणी से मुझे लगता है कि ओपी के मन में वास्तव में ऐसा नहीं था।
डॉक्टर ब्राउन

3

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


उस मामले में, अर्थात रचना को चुनना, लेकिन अभी भी जरूरत है कि प्रतिस्थापन करने के लिए विरासत में, "विरासत" नाम दिया जाएगा उदाहरण के लिए IHasWaveGenerator, और उस इंटरफ़ेस पर संबंधित विधि होगी GetWaveGeneratorजो एक उदाहरण देता है IWaveGenerator। बेशक नामकरण बदला जा सकता है। (मैं सिर्फ और अधिक विवरणों को बाहर निकालने की कोशिश कर रहा हूं - मुझे बताएं कि क्या मेरा विवरण गलत है।)
रात

2

यह NoteGeneratorइंटरफ़ेस लागू करने के लिए ठीक है, और यह भी, NoteGeneratorएक आंतरिक कार्यान्वयन के लिए है कि (रचना द्वारा) दूसरे को संदर्भित करता है IWaveGenerator

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

जब आपके पास कोई ऐसा कार्यान्वयन हो जिसे आप विशेषज्ञ बनाना चाहते हैं या अनुकूलित करना चाहते हैं, तो इनहेरिटेंस का बेहतर उपयोग किया जाता है, जो यहां नहीं लगता है: आपको केवल इंटरफ़ेस का उपयोग करने की आवश्यकता है।


1
इसे NoteGeneratorलागू करना ठीक नहीं है IWaveGeneratorक्योंकि नोटों के लिए धड़कन की आवश्यकता होती है। सेकंड नहीं-
ट्यूलेंस कोरडोवा

हां, निश्चित रूप से यदि इंटरफ़ेस का कोई समझदार कार्यान्वयन नहीं है, तो वर्ग को इसे लागू नहीं करना चाहिए। हालांकि, ओपी ने कहा कि "मैं कहूंगा कि NoteGeneratorयह वैचारिक रूप से एक है IWaveGeneratorक्योंकि यह उत्पन्न करता है SoundWave", और, वह विरासत पर विचार कर रहा था, इसलिए मैंने इस संभावना के लिए मानसिक अक्षांश लिया कि इंटरफ़ेस का कुछ कार्यान्वयन हो सकता है, हालांकि एक और है बेहतर इंटरफ़ेस या हस्ताक्षर वर्ग के लिए।
एरिक इद्दत
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.