Pola apa ini, dan haruskah saya melakukannya?

9

Saya membuat game di as3 menggunakan flash develop dan flash cs5. Semuanya berorientasi objek. Saya bertanya-tanya, haruskah saya memiliki satu kelas "gateway" yang memiliki referensi properti ke semua instantiations dari kelas lain, dan saya hanya meneruskan kelas gateway ini ke objek baru, sehingga mereka memiliki akses ke setiap kelas. Seperti itu:

 var block:Block = new Block(gateway);

 //In the block class:
 this.gateway.player.setHealth(100);
 //Or:
 this.gateway.input.lock();

Apakah ini seperti pola tunggal atau semacamnya? Haruskah saya melakukan ini?

Tetrad
sumber

Jawaban:

13

Ini disebut pola desain objek konteks , dan itu lebih baik daripada pola singleton.

  • Objek konteks membantu pengujian, karena Anda bisa meneruskan konteks tiruan ke fungsi yang ingin Anda uji. Lajang menghalanginya, karena untuk mengejek lajang kamu perlu membuatnya bukan lajang.
  • Objek konteks membuat "negara global" Anda eksplisit, dan karenanya lebih mudah untuk dipikirkan. Jika fungsi tidak mengambil objek konteks, Anda tahu itu tidak menggunakan status konteks global. Anda tidak memiliki jaminan dengan variabel lajang atau global.
  • Objek konteks sangat sedikit lebih lambat jika Anda tidak menggunakannya, karena Anda menambahkan parameter lain ke semua panggilan fungsi Anda. Mereka bisa lebih cepat daripada global jika Anda menggunakannya, dan hampir selalu lebih cepat daripada lajang.
  • Objek konteks lebih mudah diimplementasikan; biasanya mereka hidup di heap atau stack dengan cara normal. Lajang memiliki masalah rumit yang melibatkan threading dalam banyak bahasa.

Jadi tidak, ini bukan singleton, ini jauh lebih baik daripada singleton.

Namun, Anda masih melewatkan banyak negara - fakta bahwa Anda menyimpan semuanya dalam satu variabel lokal membuatnya lebih eksplisit, tetapi masih menciptakan perselisihan keprihatinan utama . Ingatlah aturan satu tanggung jawab . Masuk akal jika ada konteks yang memiliki pemain dan level saat ini - semuanya terkait - tetapi mengapa konteks yang sama memiliki input keyboard Anda?

Pertimbangkan berbagai tingkat konteks, misalnya:

  • GameplayContext - memiliki pemain, musuh, geometri level, dll.
  • InputContext - memiliki pegangan keyboard dan mouse, acara masukan, dll.
  • GraphicsContext - memiliki tekstur, pegangan jendela, dll.
  • GlobalContext - memiliki GameplayContext, GraphicsContext, dan InputContext. Di sinilah Anda ingin menerapkan pola pencari lokasi layanan , untuk dapat menukar beberapa konteks dengan yang lain sesuai kebutuhan. Dan mungkin, untuk iterasi dan pengujian cepat, ini harus dalam variabel global nyata - hanya menyadari bahwa setiap kali Anda menggunakannya, Anda sedang membangun utang teknologi .

Konteks ini masih agak membingungkan kekhawatiran - mungkin beberapa penangan event mengambil GameplayContext dan benar-benar hanya membutuhkan pemain - tetapi tanggung jawabnya jelas ditata. Anda tahu bahwa sesuatu yang menggunakan GameplayContext tidak akan memuat tekstur; sesuatu yang menggunakan InputContext tidak dapat membunuh pemain.

Komunitas
sumber
+1 Jawaban yang bagus. Beberapa masalah kecepatan atau threading tidak benar-benar berlaku dalam konteks ini (ActionScript3 tidak mendukung threading dan banyak mekanisme peningkatan kecepatan yang bekerja di C ++ tidak berlaku ketika menggunakan AS3).
bummzack
Saya tidak tahu banyak tentang AS3VM, tetapi dalam sebagian besar bahasa yang dinamis, biaya melewati / menerima / menggunakan lokal masih lebih cepat (pencarian array) daripada biaya mencari global (pencarian hash), dan jauh lebih cepat daripada memanggil fungsi (craploads of stuff) untuk mendapatkannya. Jadi saya pikir saran itu masih berlaku.
0

Ini tidak terlihat seperti pola Singleton. Cara saya memahaminya, Anda melewatkan objek dengan referensi ke objek game penting ke semua instance Anda.

Jika ini adalah pola Singleton, Anda akan memiliki:

AudioManager.getInstance().playSound(XY);

Sedangkan dalam kasus Anda, Anda mungkin memiliki:

this.gateway.getAudioManager().playSound(XY);

Pada dasarnya terlihat sama, tetapi sebenarnya tidak. Jika Anda ingin mengganti AudioManagerdengan yang baru (kelas tambahan) seperti ExtendedAudioManager, Anda akan menabrak dinding menggunakan pola Singleton. Pendekatan gateway Anda akan menangani itu dengan baik.

Kelemahan dari pendekatan Anda adalah bahwa Anda harus melewati di gatewaymana - mana. The pola pelayanan locator (diusulkan oleh Joe Wreschnig di ini benang), tampak seperti pengganti yang baik untuk "pola gerbang" Anda.

Terkadang lebih baik hanya menjalankan dengan metode yang sederhana dan langsung daripada mendesain terlalu banyak. Terutama ketika itu proyek kecil atau prototipe. Mungkin Anda bisa membuat itu gatewaysemacam variabel global .. misalnya. Game.gatewaydan jalankan dengan itu.

bummzack
sumber
-2

Sebagian besar solusi untuk masalah ini, termasuk pola Singleton, melibatkan penggunaan variabel statis. Jika Anda hanya memiliki satu pemain, Anda bisa membuat Player menjadi kelas tunggal, yang berarti Anda dapat mengakses instance Player melalui sesuatu seperti Player.currentPlayer. Banyak orang mengamuk terhadap lajang. Anda juga dapat memiliki ResourceManager atau kelas serupa yang berisi referensi statis ke berbagai variabel global yang berguna atau sangat-sangat-global. Dalam kode Anda, Anda mungkin membuat variabel "Gateway" dapat diakses secara statis alih-alih menggembungkan kode Anda dengan meneruskannya ke mana-mana.

Gregory Avery-Weir
sumber
Pertanyaannya telah banyak berubah sejak saya membuat jawaban ini, cukup sehingga sepertinya tidak layak untuk mengeditnya.
Gregory Avery-Weir
2
Selain dari judul, tidak ada yang berubah dalam pertanyaan.
bummzack
1
Apa? Tidak ada yang berubah selain judul. -1
AttackingHobo
Saya pikir saya sedang memikirkan judul di sini; Saya ingat judul aslinya berupa "Bagaimana saya harus melakukan ini?" Sangat mungkin bahwa saya salah membaca judul / pertanyaan awal ketika saya membuat jawabannya.
Gregory Avery-Weir