मैं एक परिसंपत्ति प्रबंधक के बारे में नहीं सोचकर शुरू करता हूं । शिथिल-परिभाषित शब्दों (जैसे "प्रबंधक") में आपकी वास्तुकला के बारे में सोचकर आपको गलीचा के नीचे कई विवरणों को मानसिक रूप से झाड़ने की अनुमति मिलती है, और परिणामस्वरूप समाधान पर व्यवस्थित करना अधिक कठिन हो जाता है।
अपनी विशिष्ट आवश्यकताओं पर ध्यान केंद्रित करें, जो एक संसाधन लोडिंग तंत्र बनाने के साथ प्रतीत होता है जो अंतर्निहित मूल भंडारण को अमूर्त करता है और समर्थित प्रकार के सेट की व्यापकता के लिए अनुमति देता है। आपके प्रश्न में वास्तव में कुछ भी नहीं है, उदाहरण के लिए, पहले से लोड संसाधनों का कैशिंग - जो ठीक है, क्योंकि एकल-जिम्मेदारी सिद्धांत को ध्यान में रखते हुए आपको शायद एक अलग इकाई के रूप में एक परिसंपत्ति कैश का निर्माण करना चाहिए और दो इंटरफेस को कहीं और एकत्रित करना चाहिए। , के रूप में उपयुक्त।
अपनी विशिष्ट चिंता को दूर करने के लिए, आपको अपने लोडर को डिज़ाइन करना चाहिए ताकि यह किसी भी संपत्ति का लोडिंग खुद न करे, बल्कि उस जिम्मेदारी को सौंपता है जो विशिष्ट प्रकार की संपत्ति को लोड करने के लिए इंटरफेस के अनुरूप हो। उदाहरण के लिए:
interface ITypeLoader {
object Load (Stream assetStream);
}
आप इस इंटरफ़ेस को लागू करने वाली नई कक्षाएं बना सकते हैं, प्रत्येक नई कक्षा को एक विशिष्ट प्रकार के डेटा को एक स्ट्रीम से लोड करने के अनुरूप बनाया जा सकता है। एक धारा का उपयोग करके, टाइप लोडर को एक आम, भंडारण-अज्ञेयवादी इंटरफ़ेस के खिलाफ लिखा जा सकता है, और डिस्क या डेटाबेस से लोड करने के लिए कठोर कोडित नहीं होना पड़ता है; यह आपको नेटवर्क स्ट्रीम से अपनी संपत्ति लोड करने की भी अनुमति देगा (जो आपके गेम कंसोल पर चल रहा है और नेटवर्क से जुड़े पीसी पर आपके संपादन उपकरण) जब संपत्ति को फिर से लोड करने में बहुत उपयोगी हो सकता है।
आपके मुख्य परिसंपत्ति लोडर को इन प्रकार-विशिष्ट लोडर को पंजीकृत और ट्रैक करने में सक्षम होना चाहिए:
class AssetLoader {
public void RegisterType (string key, ITypeLoader loader) {
loaders[key] = loader;
}
Dictionary<string, ITypeLoader> loaders = new Dictionary<string, ITypeLoader>();
}
यहां उपयोग की जाने वाली "कुंजी" वह हो सकती है जो आपको पसंद है - और इसे एक स्ट्रिंग की आवश्यकता नहीं है, लेकिन उन के साथ शुरू करना आसान है। मुख्य कारक यह होगा कि आप उपयोगकर्ता से किसी विशेष संपत्ति की पहचान करने की अपेक्षा कैसे करते हैं और इसका उपयोग उचित लोडर को देखने के लिए किया जाएगा। क्योंकि आप इस तथ्य को छिपाना चाहते हैं कि कार्यान्वयन एक फ़ाइल सिस्टम या डेटाबेस का उपयोग कर रहा हो सकता है, आपके पास एक फ़ाइल सिस्टम पथ या ऐसा कुछ भी करने के लिए संपत्ति का जिक्र करने वाले उपयोगकर्ता नहीं हो सकते हैं।
उपयोगकर्ताओं को एक नंगे न्यूनतम जानकारी के साथ एक संपत्ति का उल्लेख करना चाहिए। कुछ मामलों में, केवल एक फ़ाइल नाम ही पर्याप्त होगा, लेकिन मैंने पाया है कि यह अक्सर एक प्रकार / नाम जोड़ी का उपयोग करने के लिए वांछनीय है, इसलिए सब कुछ बहुत स्पष्ट है। इस प्रकार, एक उपयोगकर्ता आपके एनीमेशन XML फ़ाइलों में से एक के उदाहरण का उल्लेख कर सकता है "AnimationXml","PlayerWalkCycle"
।
यहां, AnimationXml
वह कुंजी होगी जिसके तहत आपने पंजीकरण किया था AnimationXmlLoader
, जो लागू करता हैIAssetLoader
। जाहिर है, PlayerWalkCycle
विशिष्ट संपत्ति की पहचान करता है। एक प्रकार के नाम और एक संसाधन नाम को देखते हुए, आपका एसेट लोडर उस परिसंपत्ति के कच्चे बाइट्स के लिए अपने निरंतर भंडारण को क्वेरी कर सकता है। चूंकि हम यहां अधिकतम समानता के लिए जा रहे हैं, आप इसे लोड करते समय लोडर एक्सेस के साधन को पास करके इसे लागू कर सकते हैं, जिससे आप स्टोरेज माध्यम को किसी भी चीज से बदल सकते हैं जो बाद में एक स्ट्रीम प्रदान कर सकता है:
interface IAssetStreamProvider {
Stream GetStream (string type, string name);
}
class AssetLoader {
public AssetLoader (IAssetStreamProvider streamProvider) {
provider = streamProvider;
}
object LoadAsset (string type, string name) {
var loader = loaders[type];
var stream = provider.GetStream(type, name);
return loader.Load(stream);
}
public void RegisterType (string type, ITypeLoader loader) {
loaders[type] = loader;
}
IAssetStreamProvider provider;
Dictionary<string, ITypeLoader> loaders = new Dictionary<string, ITypeLoader>();
}
एक बहुत ही सरल स्ट्रीम प्रदाता केवल एक उपनिर्देशिका नाम के लिए एक निर्दिष्ट संपत्ति रूट निर्देशिका में दिखेगा type
और name
एक धारा में नामित फ़ाइल के कच्चे बाइट्स को लोड करेगा और इसे वापस करेगा।
संक्षेप में, आपके पास यहां क्या है एक प्रणाली है:
- एक वर्ग है जो कुछ प्रकार के बैकेंड स्टोरेज (एक डिस्क, एक डेटाबेस, एक नेटवर्क स्ट्रीम, जो भी हो) से कच्चे बाइट्स को पढ़ना जानता है।
- ऐसी कक्षाएं हैं जो एक विशेष प्रकार के संसाधन में एक कच्ची बाइट स्ट्रीम को चालू करने और इसे वापस करने का तरीका जानती हैं।
- आपके वास्तविक "एसेट लोडर" में सिर्फ उपरोक्त एब्स का एक संग्रह है और यह जानता है कि स्ट्रीम प्रदाता के आउटपुट को किस प्रकार के विशिष्ट लोडर में पाइप करना है और इस प्रकार एक ठोस संपत्ति का उत्पादन होता है। स्ट्रीम प्रदाता और प्रकार-विशिष्ट लोडर को कॉन्फ़िगर करने के तरीकों को उजागर करके, आपके पास एक ऐसी प्रणाली है जिसे वास्तविक परिसंपत्ति लोडर कोड को संशोधित किए बिना ग्राहकों (या अपने आप) द्वारा बढ़ाया जा सकता है।
कुछ चेतावनी और अंतिम नोट:
उपरोक्त कोड मूल रूप से C # है, लेकिन न्यूनतम प्रयास के साथ किसी भी भाषा में अनुवाद करना चाहिए। इसे सुविधाजनक बनाने के लिए मैंने बहुत सी चीज़ों को छोड़ दिया जैसे त्रुटि जाँच या ठीक से उपयोग करना IDisposable
और अन्य मुहावरे जो अन्य भाषाओं में सीधे लागू नहीं हो सकते हैं। उन्हें पाठक के लिए होमवर्क के रूप में छोड़ दिया जाता है।
इसी तरह, मैं object
ऊपर के रूप में ठोस संपत्ति लौटाता हूं , लेकिन यदि आप चाहें, तो आप जेनरिक या टेम्प्लेट का उपयोग कर सकते हैं या जो भी अधिक विशिष्ट ऑब्जेक्ट प्रकार का उत्पादन कर सकते हैं (आप के साथ काम करना अच्छा है)।
ऊपर के रूप में, मैं यहाँ बिल्कुल भी कैशिंग से नहीं निपटता। हालांकि, आप कैशिंग को आसानी से और उसी तरह की सामान्यता और विन्यास के साथ जोड़ सकते हैं। यह कोशिश करो और देखो!
ऐसा करने के लिए बहुत सारे और बहुत सारे और बहुत सारे तरीके हैं, और निश्चित रूप से कोई एक तरीका या आम सहमति नहीं है, यही कारण है कि आप एक खोजने में सक्षम नहीं हैं। मैंने इस उत्तर को बिना दर्द के लंबी दीवार में बदलकर विशिष्ट बिंदुओं को प्राप्त करने के लिए पर्याप्त कोड प्रदान करने की कोशिश की है। यह पहले से ही बहुत लंबा है क्योंकि यह है। यदि आपके पास स्पष्ट प्रश्न हैं, तो टिप्पणी करने के लिए स्वतंत्र महसूस करें या मुझे चैट में खोजें ।