आप एक निर्माता को कैसे विघटित कर सकते हैं?


21

आइए बताते हैं कि मेरे पास एक शत्रु वर्ग है, और निर्माणकर्ता कुछ इस तरह दिखाई देगा:

public Enemy(String name, float width, float height, Vector2 position, 
             float speed, int maxHp, int attackDamage, int defense... etc.){}

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

मैं बस यह जानने की कोशिश कर रहा हूं कि कैसे सफाई से कोड बनाया जाए। अगर इससे कोई फर्क पड़ता है, तो मैं जावा / सी ++ / सी # में काम करता हूं। सही दिशा में किसी भी बिंदु की सराहना की जाती है।


5
एक कंस्ट्रक्टर होने के बारे में कुछ भी बुरा नहीं है जो सभी विशेषताओं को बांधता है। वास्तव में, कुछ हठ वातावरण में, यह आवश्यक है। कुछ भी नहीं कहता है कि आपके पास कई कंस्ट्रक्टर नहीं हो सकते हैं, शायद वैधता जाँच विधि के साथ टुकड़ा-वार निर्माण करने के बाद बुलाया जाए।
बोबडलिंगिश

1
यदि आप कभी भी शाब्दिक उपयोग करके कोड में शत्रु वस्तुओं का निर्माण करने का इरादा रखते हैं तो मुझे सवाल करना होगा। यदि आप नहीं करते हैं, और मुझे नहीं पता है कि आप क्यों करेंगे, तो ऐसे कंस्ट्रक्टर का निर्माण करें जो डेटा को डेटाबेस इंटरफ़ेस, या क्रमांकन स्ट्रिंग, या ...
Zan Lynx


जवाबों:


58

इसका समाधान है कि मापदंडों को समग्र प्रकारों में बांधा जाए। चौड़ाई और ऊंचाई वैचारिक रूप से संबंधित हैं - वे दुश्मन के आयामों को निर्दिष्ट करते हैं और आमतौर पर एक साथ की आवश्यकता होगी। उन्हें एक Dimensionsप्रकार से बदला जा सकता है , या शायद ऐसा Rectangleप्रकार जिसमें स्थिति भी शामिल हो। दूसरी ओर, यह समूह positionऔर speedएक MovementDataप्रकार में अधिक समझ में आता है , खासकर अगर त्वरण बाद में तस्वीर में प्रवेश करता है। संदर्भ से मुझे लगता है maxHp, attackDamage, defense, आदि को भी एक साथ एक से संबंधित Statsप्रकार। तो, एक संशोधित हस्ताक्षर कुछ इस तरह दिख सकता है:

public Enemy(String name, Dimensions dimensions, MovementData movementData, Stats stats)

लाइनों को कहाँ खींचना है, इसका ठीक-ठीक विवरण आपके कोड के बाकी हिस्सों पर निर्भर करेगा और डेटा का आमतौर पर एक साथ उपयोग किया जाता है।


21
मैं यह भी जोड़ना चाहूंगा कि इतने सारे मान एकल जिम्मेदारी सिद्धांत के उल्लंघन का संकेत हो सकते हैं। और विशिष्ट वस्तुओं में मूल्यों को समूहित करना उन जिम्मेदारियों को अलग करने में पहला कदम है।
युफोरिक

2
मुझे नहीं लगता कि मूल्यों की सूची एसआरपी समस्या है; उनमें से ज्यादातर शायद बेस क्लास कंस्ट्रक्टर के लिए हैं। पदानुक्रम में प्रत्येक वर्ग के पास एक ही जिम्मेदारी हो सकती है। Enemyकेवल वह वर्ग है जो लक्ष्य करता है Player, लेकिन उनके सामान्य आधार वर्ग Combatantको लड़ाई के आँकड़े चाहिए।
MSalters

@MSalters यह एसआरपी समस्या को इंगित नहीं करता है, लेकिन यह हो सकता है। यदि उसे पर्याप्त संख्या में क्रंचिंग करने की आवश्यकता है, तो वे कार्य शत्रु वर्ग में अपना रास्ता खोज सकते हैं जब उन्हें या तो स्थिर / मुक्त कार्य होना चाहिए (यदि वह सादे पुराने डेटा कंटेनर के रूप में Dimensions/ उपयोग करता है MovementData) या तरीके (यदि वह उन्हें सार डेटा में बदल देता है) प्रकार / वस्तुओं)। एक उदाहरण के रूप में, अगर वह पहले से ही एक Vector2प्रकार का निर्माण नहीं किया था , तो शायद वह वेक्टर गणित कर रहा है Enemy
डोभाल

24

आप बिल्डर पैटर्न पर एक नज़र डालना चाहते हैं । लिंक से (पैटर्न बनाम विकल्पों के उदाहरण के साथ):

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


4
एक छोटा कोड स्निपेट मददगार होगा। विभिन्न इनपुट्स के साथ जटिल वस्तुओं या संरचनाओं के निर्माण के लिए यह एक बढ़िया पैटर्न है। आप बिल्डरों को भी विशेषज्ञ बना सकते हैं, जैसा कि विभिन्न साझा गुणों को एन्कैप करने वाले EnemyABuilder, EnemyBBuilder, आदि। यह फ़ैक्टरी पैटर्न के फ्लिप पक्ष के अनुसार है (जैसा कि नीचे दिया गया है), लेकिन मेरी व्यक्तिगत प्राथमिकता बिल्डर के लिए है।
रोब

1
धन्यवाद, बिल्डर पैटर्न और फैक्टरी पैटर्न दोनों ऐसे दिखते हैं जैसे कि मैं जो कुछ करने की कोशिश कर रहा हूं उसके साथ अच्छी तरह से काम करेंगे। मुझे लगता है कि बिल्डर / फैक्टरी और डोभाल के सुझाव का एक संयोजन हो सकता है कि मैं क्या देख रहा हूं। संपादित करें: मुझे लगता है कि मैं केवल एक उत्तर को चिह्नित कर सकता हूं; मैं इसे डोभाल को दे दूंगा क्योंकि यह विषय प्रश्न का उत्तर देता है, लेकिन अन्य मेरी विशिष्ट समस्या के लिए भी उतने ही सहायक हैं। आप सभी को धन्यवाद।
ट्रैविस

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

1
@ Mark16 जैसा कि लिंक में बताया गया है, बिल्डर पैटर्न नाम के वैकल्पिक मापदंडों का अनुकरण करता है जैसा कि अडा और पायथन में पाया जाता है। आपने उल्लेख किया है कि आप प्रश्न में C # का भी उपयोग करते हैं, और यह भाषा नामित / वैकल्पिक तर्कों (C # 4.0 के रूप में) का समर्थन करती है, इसलिए यह एक और विकल्प हो सकता है।
बॉब

5

कुछ मूल्यों को निर्धारित करने के लिए उपवर्गों का उपयोग करना वांछनीय नहीं है। केवल उपवर्ग तब होता है जब किसी नए प्रकार के दुश्मन के अलग व्यवहार या नई विशेषताएँ होती हैं।

कारखाने पैटर्न आमतौर पर सटीक इस्तेमाल किया वर्ग से अधिक सार करने के लिए प्रयोग किया जाता है, लेकिन यह भी वस्तु निर्माण के लिए एक टेम्पलेट्स प्रदान करने के लिए इस्तेमाल किया जा सकता:

class EnemyFactory {

    // each of these methods is essentially a template for a kind of enemy

    Enemy enemyA(String name, ...) {
        return new Enemy(name, ..., presetValue, ...);
    }

    Enemy enemyB(String name, ...) {
        return new Enemy(name, ..., otherValue, ...);
    }

    Enemy enemyC(String name, ...) {
        return new EnemySubclass(name, ..., otherValue, ...);
    }

    ...
}

EnemyFactory factory = new EnemyFactory();
Enemy a = factory.enemyA("fred", ...);
Enemy b = factory.enemyB("willy", ...);

0

मैं उन कक्षाओं को उप-वर्गीकृत करना चाहूंगा, जो उस वस्तु का प्रतिनिधित्व करते हैं जिसे आप स्वतंत्र रूप से उपयोग करना चाहते हैं, जैसे कि चरित्र वर्ग जहां सभी वर्ण हैं, न कि केवल दुश्मनों के नाम, गति, मैक्सएचपी, या स्प्राइट का प्रतिनिधित्व करने के लिए एक वर्ग है जो चौड़ाई के साथ स्क्रीन पर मौजूद है, ऊंचाई, स्थिति।

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

आप किस भाषा का उपयोग करना चाहते हैं, इसके आधार पर, कुछ आपके निर्माता के इनपुट मापदंडों के लिए डिफ़ॉल्ट मान सेट कर सकते हैं:

Enemy(float height = 42, float width = 42);

0

रोरी हंटर के उत्तर (जावा में) को जोड़ने के लिए एक कोड उदाहरण:

public class Enemy{
   private String name;
   private float width;
   ...

   public static class Builder{
       private Enemy instance;

       public Builder(){
           this.instance = new Enemy();
       }


       public Builder withName(String name){
           instance.name = name;
           return this;
       }

       ...

       public Enemy build(){
           return instance;
       }
   }
}

अब, आप इस तरह से दुश्मन के नए उदाहरण बना सकते हैं:

Enemy myEnemy = new Enemy.Builder().withName("John").withX(x).build();

1
प्रोग्रामर दौरा वैचारिक प्रश्न हैं और चीजों की व्याख्या करने के लिए उत्तर अपेक्षित हैं । स्पष्टीकरण के बजाय कोड डंप फेंकना आईडीई से व्हाइटबोर्ड पर कोड कॉपी करने जैसा है: यह परिचित लग सकता है और यहां तक ​​कि कभी-कभी समझ में आता है, लेकिन यह अजीब लगता है ... बस अजीब है। व्हाइटबोर्ड में संकलक नहीं है
gnat
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.