सबसे पहले यदि आप "विरासत पर संरचना" का पालन करना चाहते हैं तो आपके समाधानों में से आधे से अधिक फिट नहीं होते हैं क्योंकि आप अभी भी उन लोगों में विरासत का उपयोग करते हैं।
असल में "विरासत पर संरचना" के साथ इसे लागू करने के लिए कई अलग-अलग तरीकों से मौजूद है, शायद प्रत्येक व्यक्ति के पास इसका लाभ और हानि है। पहले एक तरह से यह संभव है लेकिन वर्तमान में सी # में नहीं है। कम से कम कुछ एक्सटेंशन के साथ नहीं जो आईएल कोड को फिर से लिखता है। एक विचार आम तौर पर mixins का उपयोग करने के लिए है। तो आपके पास इंटरफेस और मिक्सिन क्लास है। एक मिक्सिन में मूल रूप से केवल वे विधियां होती हैं जो कक्षा में "इंजेक्शन" प्राप्त करती हैं। वे इससे नहीं निकलते हैं। तो अगर आप (सभी कोड छद्म कोड में है)
class RobotDog
implements interface IEat, IBark
implements mixin MEat, MBark
IEat
और IBark
, इंटरफेस प्रदान करता है, जबकि MEat
और MBark
कुछ डिफ़ॉल्ट कार्यान्वयन है कि आप इंजेक्षन सकता है के साथ mixins होगा इस तरह एक वर्ग हो सकता था। इस तरह की एक डिजाइन जावास्क्रिप्ट में संभव है, लेकिन वर्तमान में सी # में नहीं है। इसका लाभ यह है कि अंत में आपके पास RobotDog
कक्षा है जिसमें साझा किए गए कार्यान्वयन के साथ IEat
और IBark
के सभी तरीके हैं। और यह भी एक ही समय में एक नुकसान है, क्योंकि आप कई विधियों के साथ बड़ी कक्षाएं बनाते हैं। इसके शीर्ष पर विधि विवाद हो सकते हैं। उदाहरण के लिए जब आप एक ही नाम/हस्ताक्षर के साथ दो अलग-अलग इंटरफेस इंजेक्ट करना चाहते हैं। इस तरह के दृष्टिकोण के रूप में अच्छा लगता है, मुझे लगता है कि नुकसान बड़े हैं और मैं इस तरह के एक डिजाइन को प्रोत्साहित नहीं करता।
के रूप में सी # mixins का समर्थन नहीं करता सीधे आप एक्सटेंशन के तरीके इस्तेमाल कर सकते हैं किसी भी तरह से ऊपर डिजाइन फिर से बनाया है। तो आपके पास अभी भी IEat
और IBark
इंटरफेस हैं। और आप इंटरफेस के लिए एक्सटेंशन विधियां प्रदान करते हैं। लेकिन यह मिश्रण मिश्रण के रूप में एक ही नुकसान है। ऑब्जेक्ट पर सभी विधियां दिखाई देती हैं, विधि नाम टक्कर वाली समस्याएं। शीर्ष पर भी, रचना का विचार यह भी है कि आप विभिन्न कार्यान्वयन प्रदान कर सकते हैं। आप एक ही इंटरफेस के लिए अलग मिक्सिन भी हो सकते हैं। और इसके शीर्ष पर, मिश्रण कुछ प्रकार के डिफ़ॉल्ट कार्यान्वयन के लिए हैं, विचार अभी भी है कि आप एक विधि को ओवरराइट या बदल सकते हैं।
विस्तार विधि के साथ उस तरह की चीजें करना संभव है लेकिन मैं इस तरह के डिज़ाइन का उपयोग नहीं करता। आप सैद्धांतिक रूप से कई अलग-अलग नामस्थान बना सकते हैं ताकि आप किस नामस्थान को लोड कर सकें, आपको विभिन्न कार्यान्वयन के साथ अलग एक्सटेंशन विधि मिलती है। लेकिन ऐसा डिजाइन मेरे लिए और अधिक अजीब लगता है। तो मैं इस तरह के एक डिजाइन का उपयोग नहीं करता।
सामान्य तरीके से मैं इसे कैसे हल करूंगा, यह आपके इच्छित व्यवहार के लिए फ़ील्ड की अपेक्षा कर रहा है।तो आपका रोबोटडॉग इस तरह दिखता है
class RobotDog(ieat, ibark)
IEat Eat = ieat
IBark Bark = ibark
तो इसका मतलब है। आपके पास एक कक्षा है जिसमें दो गुण Eat
और Bark
शामिल हैं। वे गुण IEat
और IBark
प्रकार हैं। यदि आप RobotDog
उदाहरण बनाना चाहते हैं तो आपको एक विशिष्ट IEat
और IBark
कार्यान्वयन में प्रवेश करना होगा जिसका आप उपयोग करना चाहते हैं।
let eat = new CatEat()
let bark = new DogBark()
let robotdog = new RobotDog(eat, bark)
अब रोबोटडॉग एक बिल्ली की तरह खाएगा, और छाल की तरह छाल खाएगा। आप बस कॉल कर सकते हैं कि आपके रोबोटडॉग को क्या करना चाहिए।
robotdog.Eat.Fruit()
robotdof.Eat.Drink()
robotdog.Bark.Loud()
अब आप अपने RobotDog के व्यवहार पूरी तरह से इंजेक्शन वस्तुओं, जिससे आप अपने वस्तु के निर्माण प्रदान करते हैं पर निर्भर करता है। आप रनटाइम पर व्यवहार को किसी अन्य वर्ग के साथ भी स्विच कर सकते हैं। अपने RobotDog एक खेल में है और बार्किंग अपग्रेड हो तुम सिर्फ किसी अन्य वस्तु और व्यवहार के साथ रनटाइम पर बार्क की जगह सकता है आप इसे परिवर्तनशील है, या एक नई वस्तु बनाने के द्वारा
robotdog.Bark <- new DeadlyScreamBarking()
किसी भी तरह से करना चाहते हैं। आप एक परिवर्तनीय या अपरिवर्तनीय डिजाइन का उपयोग कर सकते हैं, यह आपके ऊपर है। तो आपके पास कोड साझा करना है। कम से कम मुझे शैली बहुत पसंद है, क्योंकि सैकड़ों तरीकों से ऑब्जेक्ट रखने की बजाय मूल रूप से अलग-अलग ऑब्जेक्ट्स वाली पहली परत होती है जिसमें प्रत्येक क्षमता को अलग-अलग अलग किया जाता है। उदाहरण के लिए यदि आप अपनी रोबोटडॉग कक्षा में स्थानांतरित करना जोड़ते हैं तो आप केवल "अचल" संपत्ति जोड़ सकते हैं और उस इंटरफ़ेस में MoveTo
, CalculatePath
, Forward
, SetSpeed
और अन्य कई विधियां हो सकती हैं। वे robotdog.Move.XYZ
के तहत स्पष्ट रूप से उपलब्ध होंगे। आपको टकराव विधियों के साथ कोई समस्या नहीं है। उदाहरण के लिए बिना किसी समस्या के प्रत्येक वर्ग पर एक ही नाम के साथ विधियां हो सकती हैं। और शीर्ष पर। आप भी एक ही प्रकार के कई व्यवहार कर सकते हैं! उदाहरण के लिए स्वास्थ्य और शील्ड एक ही प्रकार का उपयोग कर सकते हैं। उदाहरण के लिए एक साधारण "मिनमैक्स" प्रकार जिसमें न्यूनतम/अधिकतम और वर्तमान मूल्य और उन पर काम करने के तरीके शामिल हैं। स्वास्थ्य/शील्ड मूल रूप से वही व्यवहार करते हैं, और आप आसानी से इस दृष्टिकोण के साथ एक ही कक्षा में उनमें से दो का उपयोग कर सकते हैं क्योंकि कोई विधि/संपत्ति या घटना टकराव नहीं कर रही है।
robotdog.Health.Increase(10)
robotdog.Shield.Increase(10)
पिछले डिजाइन थोड़ा बदला जा सकता है, लेकिन मुझे नहीं लगता कि यह बेहतर बनाता है। लेकिन बहुत से लोग हर डिजाइन पैटर्न या कानून को मस्तिष्क से अपनाने के साथ आशा करते हैं कि यह स्वचालित रूप से सबकुछ बेहतर बनाता है। जो मैं यहां संदर्भित करना चाहता हूं उसे अक्सर Law-of-Demeter
कहा जाता है जो मुझे लगता है कि विशेष रूप से इस उदाहरण में भयानक है। असल में इस बारे में बहुत सी चर्चाएं मौजूद हैं कि यह अच्छा है या नहीं। मुझे लगता है कि यह पालन करने का एक अच्छा नियम नहीं है, और उस स्थिति में यह भी स्पष्ट हो जाता है। यदि आप इसका पालन करते हैं तो आपको अपने पास मौजूद हर ऑब्जेक्ट के लिए एक विधि लागू करना होगा। तो
robotdog.Eat.Fruit()
robotdog.Eat.Drink()
के बजाय आपको लगता है कि खाने के मैदान पर कुछ प्रणाली को बुलाती है, तो साथ क्या आप अंत किया RobotDog पर तरीकों को लागू?
robotdog.EatFruit()
robotdog.EatDrink()
तुम भी तरह
robotdog.IncreaseHealt(10)
robotdog.IncreaseShield(10)
टकराव को हल करने के लिए एक बार फिर जरूरत है वास्तव में आप सिर्फ तरीकों का एक बहुत लिखते हैं कि सिर्फ एक मैदान पर कुछ अन्य तरीकों के प्रतिनिधियों। लेकिन आपने क्या जीता? असल में कुछ भी नहीं। आपने बस एक नियम दिमाग का पालन किया। आप सैद्धांतिक रूप से कह सकते हैं। लेकिन कुछ अलग कर सकता है या Eat.Fruit()
पर कॉल करने से पहले कुछ अतिरिक्त कर सकता है।वील हाँ हो सकता है। लेकिन यदि आप अन्य अलग-अलग भोजन व्यवहार चाहते हैं तो आप केवल IEat
लागू करने वाली एक और कक्षा बनाते हैं और जब आप इसे तुरंत चालू करते हैं तो आप उस वर्ग को रोबोटडॉग को असाइन करते हैं।
उस अर्थ में, डेमेटर का कानून व्यायाम की गिनती नहीं है।
http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx/
एक निष्कर्ष के रूप में। यदि आप उस डिजाइन का पालन करते हैं तो मैं तीसरे संस्करण का उपयोग करने पर विचार करूंगा। उन गुणों का उपयोग करें जिनमें आपके व्यवहार ऑब्जेक्ट हैं, और आप सीधे उन व्यवहारों का उपयोग कर सकते हैं।
आपके उदाहरण में, जिस तरह से पशु छाल या रोबोट छाल बदलते नहीं हैं, जो गलत लगता है .... बार्क व्यवहार दोनों मामलों में अलग होगा जिसका मतलब है कि छाल विधि में जो कोड आप लिखते हैं वह अलग होगा .... – Viru
@ वीरू मैं कहूंगा कि प्रश्न में सटीक कार्य केवल चित्रकारी उद्देश्यों के लिए हैं और सचमुच नहीं लिया जाना चाहिए। इसके अलावा, मुझे यकीन है कि वहां रोबोट कुत्ते हैं जो छाल हैं। – user1666620
मुझे लगता है कि आपका केस एक समग्र पैटर्न का एक आदर्श उदाहरण है। "विरासत पर रचना का पक्ष लें": https://www.safaribooksonline.com/library/view/head-first-design/0596007124/ch01.html –