ฉันจะเริ่มต้นด้วยการไม่ได้คิดเกี่ยวกับสินทรัพย์ผู้จัดการ การคิดถึงสถาปัตยกรรมของคุณในคำศัพท์ที่กำหนดอย่างหลวม ๆ (เช่น "ผู้จัดการ") มีแนวโน้มที่จะให้คุณกวาดรายละเอียดหลายอย่างภายใต้พรมปูพื้นและทำให้ยากต่อการตัดสินใจหาทางแก้ปัญหา
มุ่งเน้นไปที่ความต้องการเฉพาะของคุณซึ่งดูเหมือนจะเกี่ยวข้องกับการสร้างกลไกการโหลดทรัพยากรที่เป็นนามธรรมที่เก็บต้นกำเนิดและช่วยให้สามารถขยายชุดประเภทที่รองรับได้ ไม่มีอะไรในคำถามของคุณเกี่ยวกับตัวอย่างเช่นการแคชทรัพยากรที่โหลดไปแล้วซึ่งไม่เป็นไรเพราะเพื่อให้สอดคล้องกับหลักการความรับผิดชอบเดี่ยวคุณควรสร้างแคชสินทรัพย์เป็นนิติบุคคลแยกต่างหากและรวมสองอินเทอร์เฟซที่อื่น ตามความเหมาะสม
เพื่อจัดการกับข้อกังวลเฉพาะของคุณคุณควรออกแบบตัวโหลดของคุณเพื่อไม่ให้โหลดเนื้อหาใด ๆ แต่ให้มอบหมายความรับผิดชอบให้กับอินเทอร์เฟซที่ปรับให้เหมาะกับการโหลดเนื้อหาประเภทใดประเภทหนึ่งโดยเฉพาะ ตัวอย่างเช่น:
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
ข้างต้น แต่คุณสามารถใช้ข้อมูลทั่วไปหรือแม่แบบหรืออะไรก็ได้ที่จะสร้างประเภทวัตถุที่เฉพาะเจาะจงมากขึ้นถ้าคุณชอบ (คุณควรจะยินดีที่ได้ทำงานด้วย)
ดังที่กล่าวไว้ข้างต้นฉันไม่ได้จัดการกับแคชเลย อย่างไรก็ตามคุณสามารถเพิ่มแคชได้อย่างง่ายดายและมีความเหมือนและความสามารถในการกำหนดค่าแบบเดียวกัน ลองดู!
มีวิธีมากมายในการทำสิ่งนี้มากมายและไม่มีทางใดที่จะเป็นฉันทามติหรือข้อตกลงร่วมกันซึ่งเป็นสาเหตุที่คุณไม่สามารถหาวิธีได้ ฉันพยายามที่จะให้รหัสเพียงพอที่จะได้รับคะแนนที่เฉพาะเจาะจงโดยไม่ต้องเปลี่ยนคำตอบนี้เป็นกำแพงยาวของรหัสที่เจ็บปวด มันมีความยาวเหลือเกิน หากคุณมีความชัดเจนคำถามความรู้สึกอิสระที่จะแสดงความคิดเห็นหรือเพื่อหาฉันในการแชท