Bagaimana cara menghindari pola tunggal untuk Penjadwal Acara?

13

Saya ingin membuat penjadwal Acara untuk Game saya, pada dasarnya saya ingin dapat menjadwalkan pemicuan Acara Game. Ini bisa menjadi pemicu satu kali, atau pemicu berkala (memicu peristiwa "E_BIG_EXPLOSION" setiap 5 detik ...).

Sangat menggoda untuk berpikir bahwa ini mungkin tempat yang baik untuk menggunakan Singleton, tetapi lajang bisa sangat jahat dan mereka cenderung menyebar seperti penyakit ... jadi saya mencoba menghindarinya dengan cara apa pun.

Desain apa yang akan Anda usulkan untuk menghindari penggunaan tunggal dalam kasus ini?

Mr.Gando
sumber
Lihat jawaban ini di alternatif untuk lajang
BlueRaja - Danny Pflughoeft

Jawaban:

12

Anda harus memiliki satu set antarmuka yang sangat terdefinisi dengan baik yang diizinkan untuk mengirim atau menerima pesan - memberi mereka referensi ke Penjadwal Acara harus sepele. Jika tidak, atau jika Anda merasa seperti itu akan melibatkan melewati penjadwal acara ke jenis "terlalu banyak" yang berbeda, maka Anda mungkin memiliki masalah desain yang lebih besar di tangan Anda (ketergantungan bebas, yang cenderung diperburuk oleh para lajang, tidak memecahkan ).

Ingat bahwa sementara teknik meneruskan penjadwal ke antarmuka yang membutuhkannya adalah bentuk " injeksi ketergantungan ," Anda tidak dalam hal ini menyuntikkan ketergantungan baru . Ini adalah dependensi yang sudah Anda miliki dalam sistem, tetapi Anda sekarang membuatnya menjadi eksplisit (versus ketergantungan implisit singleton). Sebagai aturan praktis, dependensi eksplisit lebih disukai karena mereka lebih mendokumentasikan diri.

Anda juga memberi diri Anda lebih banyak fleksibilitas dengan memisahkan para konsumen dari penjadwalan acara dari satu sama lain (karena mereka tidak semuanya terikat dengan penjadwal yang sama), yang dapat berguna untuk menguji atau mensimulasikan pengaturan klien / server lokal atau sejumlah opsi lainnya. - Anda mungkin tidak memerlukan opsi lain ini, tetapi Anda belum mengeluarkan upaya untuk secara artifisial membatasi diri dari mereka, yang merupakan nilai tambah.

EDIT: Yang saya maksud ketika saya berbicara tentang melewati penjadwal sekitar adalah ini: jika Anda memiliki beberapa komponen permainan yang bertanggung jawab untuk menanggapi tabrakan, itu mungkin dibuat melalui beberapa pabrik responden tabrakan yang merupakan bagian dari lapisan fisika Anda. Jika Anda membangun pabrik dengan instance penjadwal, maka pabrik tersebut dapat meneruskan instance tersebut ke semua responden yang dibuatnya, yang kemudian dapat menggunakannya untuk meningkatkan acara (atau mungkin berlangganan ke acara lain).

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;
}

Ini jelas merupakan contoh yang sangat dibuat-buat dan disederhanakan karena saya tidak tahu apa model objek game Anda; Namun itu menggambarkan membuat ketergantungan pada penjadwal acara eksplisit dan menunjukkan beberapa potensi untuk enkapsulasi lebih lanjut (Anda tidak perlu melewati penjawab penjadwal jika mereka berkomunikasi melalui sistem respons tabrakan tingkat yang lebih tinggi pada tingkat konseptual yang sama dengan pabrik yang berurusan dengan mur dan baut acara peningkatan melalui penjadwal. Ini akan mengisolasi setiap responden individu implementasi dari rincian implementasi sistem pengiriman acara, seperti acara tertentu untuk meningkatkan tabrakan, yang mungkin ideal untuk sistem Anda - - atau tidak).


sumber
Terima kasih atas jawaban Anda, saya memikirkan injeksi ketergantungan. Akan sangat baik jika Anda dapat menentukan solusi Anda sedikit lebih baik? (Pseudo-Code? Diagram?). Saya pikir saya mengikuti ide Anda, tapi mungkin itu hanya interpretasi saya sendiri tentang konsep itu.
Mr.Gando
Sulit melakukannya dengan cara yang bermanfaat tanpa mengetahui kelas apa yang Anda kirim / terima acara ke penjadwal.
Di Engine saya, Entitas Game mana pun dapat memiliki komponen "Event Dispatcher" yang terpasang ...
Mr.Gando
7

Penjaga acara adalah salah satu kasus di mana seorang lajang bukan ide terburuk di dunia, tetapi saya memuji Anda karena berusaha menghindarinya. Anda mungkin menemukan beberapa ide di sini .

banyak sekali
sumber
1
Terima kasih!, Setiap kali seorang singleton menciptakan Kitten Dies;)
Mr.Gando
3

Saya cenderung menghindari lajang juga, tetapi ada beberapa objek yang paling masuk akal karena lajang dan sistem pesan pusat adalah salah satunya. Terlepas dari kata-kata kasar yang saya dengar, para lajang tentu jauh lebih baik daripada variabel / fungsi global karena Anda selalu harus mengatasinya dengan sengaja (versus nilai-nilai global yang secara ajaib muncul dari udara tipis).

Pada akhirnya setiap pengirim pesan dan penerima harus memiliki beberapa titik umum persimpangan, dan itu jauh lebih baik untuk menjaga benda Anda dipisahkan dengan memiliki tunggal umum dimiliki oleh semua daripada memiliki masing-masing pengirim pesan Anda langsung tahu tentang penerima pesan.

Meskipun saya yakin beberapa arsitektur lain dapat dirancang untuk sistem acara Anda, bagi saya sepertinya membuang-buang upaya untuk terlalu memikirkannya, terutama ketika menggunakan sistem acara sudah merupakan kemenangan besar karena tidak menggunakan satu.

EDIT: Adapun contoh spesifik Anda dari peristiwa ledakan dikirim pada pemicu periodik, saya mungkin akan memiliki peristiwa dikirim di beberapa objek lain (seperti senapan menara atau apa pun yang menyebabkan ledakan itu) dan bukan dalam sistem acara pusat. Namun acara-acara itu masih akan dikirim ke sistem acara pusat.

jhocking
sumber