ฉันรู้ว่าการมีตัวแปรส่วนกลางหรือคลาสเดี่ยวสร้างกรณีที่ยากต่อการทดสอบ / จัดการและฉันถูกจับในการใช้รูปแบบเหล่านั้นในรหัส แต่บ่อยครั้งที่คุณต้องจัดส่ง
มีกรณีที่ตัวแปรระดับโลกหรือซิงเกิลตันมีประโยชน์จริง ๆ ในการพัฒนาเกมหรือไม่?
ฉันรู้ว่าการมีตัวแปรส่วนกลางหรือคลาสเดี่ยวสร้างกรณีที่ยากต่อการทดสอบ / จัดการและฉันถูกจับในการใช้รูปแบบเหล่านั้นในรหัส แต่บ่อยครั้งที่คุณต้องจัดส่ง
มีกรณีที่ตัวแปรระดับโลกหรือซิงเกิลตันมีประโยชน์จริง ๆ ในการพัฒนาเกมหรือไม่?
คำตอบ:
สิ่งเหล่านี้มีประโยชน์เสมอ ไม่ว่าจะเป็นทางออกที่สวยที่สุดหรือปลอดภัยที่สุดเป็นอีกเรื่องหนึ่ง แต่ฉันคิดว่าการพัฒนาเกมเกี่ยวข้องกับการปฏิบัติในระดับหนึ่ง
รายการที่ไม่ครบถ้วน แต่แน่นอนไปที่:
เราใช้ "โครงสร้างของซิงเกิลทั่วโลก" มากมายในเกมพกพาของเรา ชื่อพีซีและคอนโซลมักใช้น้อยกว่า เราจะเปลี่ยนไปสู่สถาปัตยกรรมที่ขับเคลื่อนด้วยเหตุการณ์ / การส่งข้อความ ที่ได้รับการกล่าวชื่อ PC / คอนโซลยังคงมักจะใช้ TextureManager กลาง; เนื่องจากโดยปกติแล้วจะห่อทรัพยากรที่ใช้ร่วมกันเดียว (หน่วยความจำพื้นผิว) สิ่งนี้เหมาะสมสำหรับเรา
หากคุณรักษา API ของคุณให้สะอาดอยู่เสมอมันอาจไม่ยากที่จะปรับโครงสร้างออกจาก (หรือเป็น!) รูปแบบซิงเกิลเมื่อคุณต้องการ ...
สิ่งเหล่านี้มีประโยชน์มากโดยเฉพาะในช่วงการสร้างต้นแบบหรือการทดลองใช้ แต่โดยทั่วไปเราต้องการส่งผ่านการอ้างอิงสำหรับผู้จัดการเช่นโครงสร้างอย่างน้อยที่สุดคุณก็สามารถควบคุมได้ว่าพวกเขาเข้าถึงจากที่ใด ปัญหาที่ใหญ่ที่สุดเกี่ยวกับ globals และ singletons (ในความคิดของฉัน) คือพวกเขาไม่ได้เป็นมิตรกับผู้ใช้หลายเธรดและรหัสที่ใช้พวกเขานั้นยากต่อการย้ายพอร์ตไปยังหน่วยความจำที่ไม่แชร์เช่น SPU
ฉันจะบอกว่าการออกแบบเดี่ยวนั้นไม่ได้มีประโยชน์เลย ตัวแปรทั่วโลกมีประโยชน์แน่นอน แต่ฉันอยากเห็นพวกเขาซ่อนอยู่หลังอินเทอร์เฟซที่เขียนอย่างดีเพื่อที่คุณจะไม่ได้ตระหนักถึงการมีอยู่ของพวกเขา ด้วยซิงเกิลคุณจะต้องตระหนักถึงการมีอยู่ของพวกเขาอย่างแน่นอน
ฉันมักจะใช้ตัวแปรระดับโลกสำหรับสิ่งต่าง ๆ ที่จำเป็นต้องเข้าถึงได้ตลอดทั้งเครื่องยนต์ เครื่องมือประสิทธิภาพของฉันเป็นหนึ่งในตัวอย่างที่ดีที่ฉันใช้ทั่วเครื่องยนต์เพื่อโทร การโทรนั้นง่าย ProbeRegister (), ProbeHit () และ ProbeScoped () การเข้าถึงที่แท้จริงของพวกเขานั้นยุ่งยากเล็กน้อยและใช้ตัวแปรระดับโลกสำหรับบางสิ่ง
ปัญหาหลักที่เกิดขึ้นกับ globals และการใช้งานซิงเกิลตันที่ไม่ดีคือข้อผิดพลาดในการก่อสร้างและการสร้างโครงสร้างที่ไม่ชัดเจน
ดังนั้นหากคุณทำงานกับ primitives ที่ไม่มีปัญหาเหล่านี้หรือทราบปัญหาของตัวชี้อย่างมาก จากนั้นสามารถใช้งานได้อย่างปลอดภัย
ลูกโลกมีสถานที่เช่นเดียวกับ gotos และไม่ควรออกจากมือ แต่ควรใช้ด้วยความระมัดระวัง
มีคำอธิบายที่ดีในคู่มือสไตล์ Google C ++
Globals มีประโยชน์ในขณะที่สร้างต้นแบบระบบที่ต้องการสถานะระหว่างการเรียกฟังก์ชัน เมื่อคุณสร้างระบบได้แล้วให้ย้ายสถานะไปเป็นคลาสและทำให้ฟังก์ชันเป็นวิธีของคลาสนั้น
Singletons มีประโยชน์ในการทำให้เกิดปัญหากับตัวคุณเองและผู้อื่น ยิ่งคุณมีสถานะโกลบอลมากเท่าไหร่คุณจะมีปัญหามากขึ้นเกี่ยวกับความถูกต้องของรหัสการบำรุงรักษาความสามารถในการขยายความพร้อมกันและอื่น ๆ
ฉันมักจะแนะนำให้ใช้คอนเทนเนอร์ DI / IoC บางประเภทกับการจัดการอายุการใช้งานที่กำหนดเองแทน singletons (แม้ว่าคุณจะใช้ตัวจัดการอายุการใช้งาน "อินสแตนซ์เดียว") อย่างน้อยก็ง่ายที่จะสลับการใช้งานเพื่ออำนวยความสะดวกในการทดสอบ
หากคุณต้องการคุณสมบัติการประหยัดหน่วยความจำของซิงเกิลตันคุณอาจลองใช้รูปแบบการออกแบบฟลายเวท?
http://en.wikipedia.org/wiki/Flyweight_pattern
เท่าที่มีปัญหาหลายเธรดที่กล่าวถึงข้างต้นมันควรจะค่อนข้างง่ายด้วยความสุขุมในการใช้กลไกการล็อคสำหรับทรัพยากรที่อาจถูกแชร์ระหว่างเธรด http://en.wikipedia.org/wiki/Read/write_lock_pattern
Singletons เป็นวิธีที่ยอดเยี่ยมในการจัดเก็บสถานะที่ใช้ร่วมกันในแบบตัวอย่างต้น
พวกเขาไม่ใช่ bullet เงินและมาพร้อมกับปัญหาบางอย่าง แต่เป็นรูปแบบที่มีประโยชน์มากสำหรับ UI / ลอจิกบางอย่าง
ตัวอย่างเช่นใน iOS คุณใช้ singletons เพื่อรับ [UIApplication sharedApplication] ใน cocos2d คุณสามารถใช้มันเพื่อรับการอ้างอิงถึงวัตถุบางอย่างเช่น [CCNotifications sharedManager] และโดยส่วนตัวแล้วฉันมักจะเริ่มต้นด้วย [Game sharedGame] singleton ที่ฉันสามารถทำได้ สถานะร้านค้าที่แชร์ระหว่างองค์ประกอบที่แตกต่างกันมากมาย
ว้าวนี่น่าสนใจสำหรับฉันเพราะฉันไม่เคยมีปัญหากับรูปแบบซิงเกิล โปรเจ็กต์ปัจจุบันของฉันคือเอ็นจิ้นเกม C ++ สำหรับ Nintendo DS และฉันใช้เครื่องมือการเข้าถึงฮาร์ดแวร์มากมาย (เช่น VRAM Banks, Wifi, เอ็นจิ้นกราฟิกสองตัว) เป็นอินสแตนซ์เดี่ยวเพราะพวกมันตั้งใจจะห่อหุ้ม C ทั่วโลก ฟังก์ชั่นในห้องสมุดต้นแบบ
เฉพาะเมื่อคุณมีรายการที่มีตัวควบคุมเพียงตัวเดียว แต่ถูกจัดการโดยโมดูลหลายตัว
เช่นอินเทอร์เฟซเมาส์ หรืออินเตอร์เฟซจอยสติ๊ก หรือเครื่องเล่นเพลง หรือเครื่องเล่นเสียง หรือหน้าจอ หรือผู้จัดการไฟล์บันทึก
Globals เร็วกว่ามาก! ดังนั้นมันจะเหมาะอย่างยิ่งสำหรับแอปพลิเคชั่นที่ต้องการประสิทธิภาพเช่นเกม
Singletons เป็น IMO ระดับโลกที่ดีกว่าและเป็นเครื่องมือที่เหมาะสม
ใช้เท่าที่จำเป็น!