Pertanyaan bagus! Sebelum saya sampai pada pertanyaan spesifik yang Anda ajukan, saya akan mengatakan: jangan meremehkan kekuatan kesederhanaan. Tenpn benar. Ingatlah bahwa semua yang Anda coba lakukan dengan pendekatan ini adalah menemukan cara yang elegan untuk menunda panggilan fungsi atau memisahkan penelepon dari callee. Saya dapat merekomendasikan coroutine sebagai cara intuitif yang mengejutkan untuk mengatasi beberapa masalah tersebut, tapi itu sedikit di luar topik. Terkadang, Anda lebih baik hanya memanggil fungsi dan hidup dengan fakta bahwa entitas A digabungkan langsung ke entitas B. Lihat YAGNI.
Yang mengatakan, saya telah menggunakan dan senang dengan model sinyal / slot dikombinasikan dengan pesan sederhana yang lewat. Saya menggunakannya di C ++ dan Lua untuk judul iPhone yang cukup sukses yang memiliki jadwal yang sangat ketat.
Untuk kasus sinyal / slot, jika saya ingin entitas A melakukan sesuatu sebagai respons terhadap sesuatu yang dilakukan entitas B (mis. Membuka kunci pintu ketika sesuatu mati) Saya mungkin memiliki entitas A yang berlangganan langsung ke peristiwa kematian entitas B. Atau mungkin entitas A akan berlangganan masing-masing grup entitas, menambah penghitung pada setiap peristiwa yang dipecat, dan membuka kunci pintu setelah N dari mereka telah meninggal. Juga, "grup entitas" dan "N dari mereka" biasanya akan menjadi desainer yang didefinisikan dalam data level. (Sebagai tambahan, ini adalah satu area di mana coroutine benar-benar dapat bersinar, misalnya, WaitForMultiple ("Dying", entA, entB, entC); door.Unlock ();)
Tapi itu bisa menjadi rumit ketika datang ke reaksi yang tergabung erat dengan kode C ++, atau kejadian game yang secara inheren sesaat: menangani kerusakan, memuat ulang senjata, men-debug, umpan balik AI berbasis lokasi yang digerakkan oleh pemain. Di sinilah pesan lewat dapat mengisi celah. Ini pada dasarnya bermuara pada sesuatu seperti, "beri tahu semua entitas di area ini untuk menerima kerusakan dalam 3 detik," atau "setiap kali Anda menyelesaikan fisika untuk mencari tahu siapa yang saya tembak, minta mereka untuk menjalankan fungsi skrip ini." Sulit untuk mengetahui bagaimana melakukannya dengan baik menggunakan terbitkan / berlangganan atau sinyal / slot.
Ini bisa dengan mudah berlebihan (dibandingkan contoh tenpn). Ini juga bisa menjadi mengasapi yang tidak efisien jika Anda memiliki banyak tindakan. Namun terlepas dari kekurangannya, pendekatan "pesan dan acara" ini sangat cocok dengan kode permainan yang ditulis (misalnya dalam Lua). Kode skrip dapat mendefinisikan dan bereaksi terhadap pesan dan acara sendiri tanpa kode C ++ peduli sama sekali. Dan kode skrip dapat dengan mudah mengirim pesan yang memicu kode C ++, seperti mengubah level, memutar suara, atau bahkan hanya membiarkan senjata mengatur berapa banyak kerusakan yang diberikan pesan TakeDamage. Ini menghemat banyak waktu karena saya tidak harus terus-menerus bermain-main dengan luabind. Dan itu membiarkan saya menyimpan semua kode luabind saya di satu tempat, karena tidak banyak. Bila digabungkan dengan benar,
Juga, pengalaman saya dengan use case # 2 adalah bahwa Anda lebih baik menanganinya sebagai acara di arah lain. Alih-alih bertanya apa kesehatan entitas, nyalakan acara / kirim pesan setiap kali kesehatan membuat perubahan signifikan.
Dalam hal antarmuka, btw, saya berakhir dengan tiga kelas untuk mengimplementasikan semua ini: EventHost, EventClient, dan MessageClient. EventHosts membuat slot, EventClients berlangganan / sambungkan ke dalamnya, dan MessageClients mengaitkan delegasi dengan pesan. Perhatikan bahwa target delegasi MessageClient tidak harus berupa objek yang sama yang memiliki asosiasi. Dengan kata lain, MessageClients dapat ada hanya untuk meneruskan pesan ke objek lain. FWIW, metafora host / klien agak tidak pantas. Sumber / Sink mungkin konsep yang lebih baik.
Maaf, saya agak mengoceh di sana. Ini jawaban pertama saya :) Saya harap ini masuk akal.