วิธีหลีกเลี่ยงรูปแบบซิงเกิลสำหรับ Event Scheduler


13

ฉันต้องการสร้าง Event scheduler สำหรับเกมของฉันโดยพื้นฐานแล้วฉันต้องการที่จะสามารถกำหนดตารางเวลาการเรียกเหตุการณ์ของเกมได้ นี่อาจเป็นทริกเกอร์ครั้งเดียวหรือทริกเกอร์เป็นระยะ (เหตุการณ์ทริกเกอร์ "E_BIG_EXPLOSION" เป็นเวลา 5 วินาที ... )

มันน่าดึงดูดที่จะคิดว่านี่อาจเป็นสถานที่ที่ดีในการใช้ซิงเกิลตัน แต่ซิงเกิลนั้นค่อนข้างชั่วร้ายและพวกเขามักจะแพร่กระจายอย่างโรค ... ดังนั้นฉันจึงพยายามหลีกเลี่ยงพวกเขาทั้งหมด

คุณจะเสนอการออกแบบแบบใดเพื่อหลีกเลี่ยงการใช้งานแบบซิงเกิลในกรณีนี้


ดูคำตอบนี้เมื่อต้องการสลับเป็นซิงเกิล
BlueRaja - Danny Pflughoeft

คำตอบ:


12

คุณควรมีชุดอินเทอร์เฟซที่กำหนดไว้อย่างดีซึ่งได้รับอนุญาตให้ส่งหรือรับข้อความ - ให้การอ้างอิงถึง EventScheduler ควรให้ความสำคัญ หากไม่ใช่หรือถ้าคุณรู้สึกว่าเกี่ยวข้องกับการส่งตัวกำหนดเวลาเหตุการณ์ไปยังประเภทที่แตกต่างกัน "มากเกินไป" คุณอาจมีปัญหาในการออกแบบที่ใหญ่กว่าในมือของคุณ (การพึ่งพาอาศัยสำส่อน )

โปรดจำไว้ว่าในขณะที่เทคนิคการส่งตัวกำหนดตารางเวลาไปยังอินเทอร์เฟซที่ต้องการเป็นรูปแบบของ " การฉีดขึ้นต่อกัน " คุณไม่ได้อยู่ในกรณีนี้ในการฉีดการพึ่งพาใหม่ นี่คือการพึ่งพาที่คุณมีอยู่แล้วในระบบ แต่ตอนนี้คุณกำลังทำให้เป็นสิ่งที่ชัดเจน (เทียบกับการพึ่งพาโดยนัยของซิงเกิล) ในฐานะที่เป็นกฎง่ายๆการอ้างอิงที่ชัดเจนมีความเหมาะสมมากกว่าเนื่องจากมีการจัดทำเอกสารด้วยตนเอง

นอกจากนี้คุณยังมีความยืดหยุ่นมากขึ้นด้วยการแยกกลุ่มผู้บริโภคของการกำหนดเวลาเหตุการณ์จากกัน (เนื่องจากไม่จำเป็นต้องเชื่อมโยงกับตัวกำหนดตารางเวลาเดียวกัน) ซึ่งจะเป็นประโยชน์สำหรับการทดสอบหรือจำลองการตั้งค่าไคลเอนต์ / เซิร์ฟเวอร์ในท้องถิ่นหรือตัวเลือกอื่น ๆ - คุณอาจไม่ต้องการตัวเลือกอื่น ๆ แต่คุณยังไม่ได้ใช้ความพยายามในการ จำกัด ตัวเองจากสิ่งเหล่านี้ซึ่งเป็นข้อดี

แก้ไข: ทั้งหมดที่ฉันหมายถึงเมื่อฉันพูดถึงการส่งตัวกำหนดตารางเวลาไปรอบ ๆ คือ: ถ้าคุณมีองค์ประกอบของเกมที่รับผิดชอบในการตอบสนองต่อการชนมันอาจสร้างจากโรงงานตอบกลับการชนที่เป็นส่วนหนึ่งของชั้นฟิสิกส์ของคุณ หากคุณสร้างโรงงานด้วยอินสแตนซ์ของตัวจัดตารางเวลาโรงงานสามารถส่งต่ออินสแตนซ์นั้นไปยังผู้เผชิญเหตุที่สร้างขึ้นซึ่งสามารถใช้ประโยชน์จากการเพิ่มกิจกรรม (หรืออาจสมัครสมาชิกกิจกรรมอื่น ๆ )

class CollisionResponderFactory {
  public CollisionResponderFactory (EventScheduler scheduler) {
     this.scheduler = scheduler;
  }

  CollisionResponder CreateResponder() {
    return new CollisionResponder(scheduler);
  }

  EventScheduler scheduler;
}

class CollisionResponder {
  public CollisionResponder (EventScheduler scheduler) {
    this.scheduler = scheduler;
  }

  public void OnCollision(GameObject a, GameObject b) {
    if(a.IsBullet) {
      scheduler.RaiseEvent(E_BIG_EXPLOSION);
    }
  }

  EventScheduler scheduler;
}

เห็นได้ชัดว่านี่เป็นตัวอย่างที่เรียบง่ายและมีการวางแผนอย่างมากเนื่องจากฉันไม่รู้ว่าแบบจำลองวัตถุเกมของคุณคืออะไร; อย่างไรก็ตามมันแสดงให้เห็นถึงการทำให้การพึ่งพาตัวจัดกำหนดการเหตุการณ์อย่างชัดเจนและแสดงให้เห็นถึงความเป็นไปได้บางอย่างสำหรับการห่อหุ้มเพิ่มเติม (คุณไม่จำเป็นต้องผ่านการตอบกลับตัวกำหนดตารางเวลาหากพวกเขาสื่อสารผ่านระบบตอบสนองการชนระดับสูงกว่า โรงงานที่จัดการกับถั่วและสลักเกลียวของการเพิ่มเหตุการณ์ผ่านตัวกำหนดตารางเวลาซึ่งจะแยกการดำเนินการตอบกลับแต่ละรายจากการใช้งานรายละเอียดของระบบการจัดส่งเหตุการณ์เช่นเหตุการณ์เฉพาะที่จะยกระดับการชนกันซึ่งอาจเหมาะสำหรับระบบของคุณ - - หรือไม่).


ขอบคุณสำหรับคำตอบของคุณฉันคิดเกี่ยวกับการฉีดพึ่งพา มันจะดีมากถ้าคุณสามารถระบุโซลูชันของคุณได้ดีขึ้นเล็กน้อย? (Pseudo-Code? Diagram?) ฉันคิดว่าฉันทำตามความคิดของคุณ แต่อาจเป็นเพียงการตีความแนวคิดของฉันเอง
Mr.Gando

เป็นการยากที่จะทำในลักษณะที่มีประโยชน์โดยไม่ทราบว่าคลาสของคุณส่ง / รับกิจกรรมไปยังตัวกำหนดตารางเวลา

ใน Engine ของฉัน Entity ของเกมใด ๆ สามารถมีองค์ประกอบ "Event Dispatcher" ติดตั้งอยู่ ...
Mr.Gando

7

ผู้จัดงานอีเวนต์เป็นหนึ่งในกรณีที่ซิงเกิลตันไม่ใช่ความคิดที่เลวร้ายที่สุดในโลก แต่ฉันขอชื่นชมคุณที่พยายามหลีกเลี่ยง คุณอาจพบความคิดบางอย่างที่นี่


1
ขอบคุณ! ทุกครั้งที่มีการสร้างซิงเกิล Kitten;)
Mr.Gando

3

ฉันมักจะหลีกเลี่ยงซิงเกิลตันด้วย แต่ก็มีบางวัตถุที่เหมาะสมที่สุดสำหรับซิงเกิลและระบบส่งข้อความกลางเป็นหนึ่งในนั้น แม้จะมีคำพูดพร่ำเพ้อที่ฉันเคยได้ยินซิงเกิลตันนั้นดีกว่าตัวแปร / ฟังก์ชั่นระดับโลกอย่างแน่นอนเพราะคุณต้องพูดกับมันอย่างจงใจ (เทียบกับค่านิยมระดับโลก

ในท้ายที่สุดทุกผู้ส่งข้อความและผู้รับต้องมีบางจุดร่วมกันของสี่แยกและมันจะดีกว่ามากที่จะทำให้วัตถุของคุณหลุดพ้นโดยมีเดี่ยวร่วมกันโดยทุกอย่างมากกว่าที่มีอยู่ในแต่ละของผู้ส่งข้อความของคุณโดยตรงรู้เกี่ยวกับการรับข้อความ

ในขณะที่ฉันแน่ใจว่าสถาปัตยกรรมอื่น ๆ อาจได้รับการออกแบบสำหรับระบบเหตุการณ์ของคุณสำหรับฉันดูเหมือนว่าเสียความพยายามมากไปกว่าที่คิดไว้โดยเฉพาะเมื่อใช้ระบบเหตุการณ์เป็นชัยชนะที่ยิ่งใหญ่ไม่ใช่การใช้

แก้ไข: สำหรับตัวอย่างที่เฉพาะเจาะจงของคุณเกี่ยวกับเหตุการณ์ระเบิดที่ส่งไปเป็นระยะฉันอาจจะมีเหตุการณ์ที่ส่งในวัตถุอื่น ๆ (เช่นปืนป้อมปืนหรือสิ่งที่ทำให้เกิดการระเบิด) และไม่ได้อยู่ในระบบเหตุการณ์กลาง อย่างไรก็ตามเหตุการณ์เหล่านั้นจะยังคงถูกส่งไปยังระบบเหตุการณ์กลาง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.