Bu hangi desen ve yapmalıyım?


9

As3'te flash geliştirme ve flash cs5 kullanarak bir oyun yapıyorum. Her şey nesne yönelimlidir. Merak ediyordum, diğer sınıfların tüm örneklemelerine özellik referansı olan bir "ağ geçidi" sınıfına sahip olsaydım ve bu ağ geçidi sınıfını yeni nesnelere geçiririm, böylece her sınıfa erişebilirler. Şöyle ki:

 var block:Block = new Block(gateway);

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

Bu tekil bir kalıp gibi mi? Bunu yapmalı mıyım?

Yanıtlar:


13

Buna bağlam nesnesi tasarım deseni denir ve singleton deseninden daha iyidir.

  • Bağlam nesneleri sınamaya yardımcı olur, çünkü sınamak istediğiniz işlevleri sınamak istediğiniz işlevlere iletebilirsiniz. Singletons bunu engeller, çünkü singletonları alay etmek için onları singletons yapmamalısınız.
  • Bağlam nesneleri "küresel durumunuzu" açık ve bu nedenle akıl yürütmeyi kolaylaştırır. Bir işlev bir bağlam nesnesi almazsa, herhangi bir genel bağlam durumu kullanmadığını bilirsiniz. Tekil değişkenlerle veya global değişkenlerle böyle bir garantiniz yok.
  • Bağlam nesneleri, bunları kullanmazsanız çok yavaşlar, çünkü tüm işlev çağrılarınıza başka bir parametre eklersiniz. Bunları kullanırsanız küresellerden daha hızlı olabilirler ve neredeyse her zaman tektonlardan daha hızlıdırlar.
  • Bağlam nesnelerinin uygulanması daha kolaydır; genellikle yığın veya yığın üzerinde normal şekilde yaşarlar. Singletonların birçok dilde diş çekme ile ilgili zor sorunları vardır.

Yani hayır, bu bir singleton değil, bir singletondan çok daha iyi.

Bununla birlikte, hala bir devlet yığınından geçiyorsunuz - hepsini tek bir yerel değişkente tuttuğunuz gerçeği, onu daha açık hale getiriyor, ancak yine de endişelerin büyük bir birleşimini yaratıyor . Sorumluluk kurallarından birini unutmayın. Oynatıcıya ve mevcut seviyeye sahip bir bağlam olması mantıklıdır - bunlar ilişkilidir - ama aynı bağlam neden klavye girişinize sahip?

Farklı bağlam düzeylerini düşünün, örneğin:

  • GameplayContext - oyuncuya, düşmanlara, seviye geometrisine vb. Sahiptir.
  • InputContext - klavye ve fare tutamaçlarına, giriş olaylarına vb. Sahiptir.
  • GraphicsContext - dokulara, pencere tutamağına vb. Sahiptir.
  • GlobalContext - GameplayContext, GraphicsContext ve InputContext öğelerine sahiptir. Bu, gerektiğinde diğerleri için bazı bağlamları değiştirebilmek için servis bulucu modelini uygulamak istediğiniz yerdir . Ve belki, hızlı yineleme ve test için, bunun gerçek bir küresel değişkente olması gerekir - sadece bunu her kullandığınızda teknoloji borcu oluşturduğunuzu anlayın .

Bu bağlamlar hala endişeleri bir şekilde sınırlandırmaktadır - belki bazı olay işleyicileri GameplayContext'i alır ve gerçekten sadece oyuncuya ihtiyaç duyar - ancak sorumluluklar açıkça belirtilir. GameplayContext alan bir şeyin bir doku yüklemeyeceğini biliyorsunuz; InputContext alan bir şey bir oyuncuyu öldüremez.


+1 İyi cevap. Hız veya diş çekme endişelerinden bazıları bu bağlamda gerçekten geçerli değildir (ActionScript3, diş açmayı desteklemez ve C ++ ile çalışan çok sayıda hız iyileştirme mekanizması AS3 kullanırken geçerli değildir).
bummzack

AS3VM hakkında çok şey bilmiyorum, ancak çoğu dinamik dilde, yerel bir geçiş / alma / kullanma maliyeti, küresel (karma arama) arama maliyetinden hala daha hızlı (dizi arama) ve daha hızlı ona ulaşmak için bir işlevi çağırmak (craploads). Bu yüzden tavsiye hala geçerli.

0

Bu Singleton modeline benzemiyor. Anladığım gibi, önemli oyun nesnelerine referansları olan bir nesneyi tüm örneklerinize geçiriyorsunuz.

Bu Singleton kalıbı olsaydı, sahip olacaktınız:

AudioManager.getInstance().playSound(XY);

Halbuki sizin durumunuzda şunlar olabilir:

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

Temelde aynı görünüyor, ama gerçekten değil. AudioManagerYeni bir (genişletilmiş sınıf) ile değiştirmek isterseniz ExtendedAudioManager, Singleton desenini kullanarak bir duvara çarpacaksınız. Ağ geçidi yaklaşımınız bunu iyi halledecektir.

Yaklaşımınızın dezavantajı, her yerden geçmeniz gatewaygerekmesidir. Hizmet bulucu desen (Joe Wreschnig önerdiği bu parçacığı), senin "ağ geçidi deseni" için iyi bir yerine koyma gibi görünüyor.

Bazen işleri aşırı tasarlamak yerine basit ve anlaşılır bir yöntemle çalıştırmak daha iyidir. Özellikle küçük bir proje veya bir prototip olduğunda. Belki bir gatewayçeşit küresel değişken yapabilirsiniz .. örn. Game.gatewayve onunla koş.


-2

Singleton şablonu da dahil olmak üzere, bu soruna yönelik çoğu çözüm statik değişkenlerin kullanımını içerir. Yalnızca bir oyuncunuz olacaksa, Player'ın tek bir sınıf olmasını sağlayabilirsiniz, yani Player örneğine Player.currentPlayer gibi bir şeyle erişebilirsiniz. Ancak birçok kişi Singletons'a karşı öfkeleniyor. Ayrıca, çeşitli yararlı küresel veya oldukça darn-global değişkenlere statik başvurular içeren bir ResourceManager veya benzer bir sınıfınız olabilir. Kodunuzda, kodunuzu her yerde geçirerek şişirmek yerine "Ağ Geçidi" değişkenlerini statik olarak erişilebilir hale getirebilirsiniz.


Bu cevabı verdiğimden beri soru önemli ölçüde değişti, yeterince düzeltmeye değmez.
Gregory Avery-Weir

2
Başlık dışında, soruda hiçbir şey değişmedi.
bummzack

1
Ne? Başlık dışında hiçbir şey değişmedi. -1
AttackingHobo

Sanırım burada unvanı düşünüyordum; Orijinal başlığın "Bunu nasıl yapmalıyım?" Cevabı verdiğimde ilk başlığı / soruyu yanlış okumam tamamen mümkündür.
Gregory Avery-Weir
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.