Bir strateji kalıbı ve bir komut kalıbı kullanmak


121

Her iki tasarım deseni de bir algoritmayı içerir ve uygulama ayrıntılarını çağıran sınıflardan ayırır. Benim ayırt edebildiğim tek fark, Strateji modelinin yürütme için parametreleri alırken Komut kalıbı almıyor olmasıdır.

Bana öyle geliyor ki komut kalıbı, çalıştırma için tüm bilgilerin yaratıldığında kullanılabilir olmasını gerektiriyor ve çağrılmasını geciktirebiliyor (belki de bir komut dosyasının parçası olarak).

Bir modelin mi yoksa diğerinin mi kullanılacağına karar veren nedir?

Yanıtlar:


94

Bu iki model arasındaki farkları açıklamaya yardımcı olması için çeşitli GoF tasarım modellerinin bir kapsülleme hiyerarşi tablosu ekliyorum. Umarım her birinin kapsadığı şeyi daha iyi gösterir, böylece açıklamam daha mantıklı olur.

İlk olarak, hiyerarşi, tablonun hangi tarafında başladığınıza bağlı olarak, belirli bir modelin uygulanabilir olduğu kapsamı veya bir miktar ayrıntıyı kapsüllemek için kullanılacak uygun modeli listeler.

tasarım deseni kapsülleme hiyerarşi tablosu

Tablodan da görebileceğiniz gibi, bir Strateji Modeli nesnesi, bir algoritmanın uygulamasının ayrıntılarını gizler, bu nedenle farklı bir strateji nesnesinin kullanılması aynı işlevi, ancak farklı bir şekilde gerçekleştirecektir. Her strateji nesnesi belirli bir faktör için optimize edilebilir veya başka bir parametre üzerinde çalışabilir; ve ortak bir arayüzün kullanılmasıyla, bağlam her ikisiyle de güvenle çalışabilir.

Komut Modeli, bir algoritmadan çok daha küçük bir ayrıntı düzeyini kapsüller. Bir nesneye mesaj göndermek için gereken ayrıntıları kodlar: alıcı, seçici ve argümanlar. Süreç yürütmenin bu kadar küçük bir bölümünü nesneleştirmenin yararı, bu tür mesajların, ayrıntılarını sabit bir şekilde kodlamak zorunda kalmadan genel bir şekilde farklı zaman veya konum noktalarında çağrılabilmesidir. Mesajların bir veya daha fazla kez çağrılmasına veya belirli bir çağrının ayrıntılarının yürütülmeden önce bilinmesine gerek kalmadan sistemin farklı bölümlerine veya çoklu sistemlere aktarılmasına izin verir.

Tasarım desenleri için tipik olduğu gibi, desen adını taşımak için tüm uygulamaların ayrıntılı olarak aynı olmasını gerektirmezler. Ayrıntılar, uygulamada ve nesnede hangi verilerin kodlandığına karşı yöntem bağımsız değişkenlerine göre değişebilir.


Öyleyse, sonuçları bir "filtre boru hattı" ile filtreleyen ve temsilcileri filtreler olarak kullanan (filtrenin algoritmalarının her birinin bir işlev içinde kapsüllendiği) bir sistemim olsaydı, bu bir Komut modeli olarak kabul edilir miydi? Bu durumda, filtre işlevi için temsilcinin, her filtrenin girdi ve çıktı açısından nelere uyması gerektiği konusunda bir çeşit sözleşme sağladığını görüyorum.
KTF

4
@KTF, hayır. Komut kalıbı, bir nesnenin yöntemini çağırmak için ihtiyaç duyulan bilgilerin (örneğin, alıcı, seçici, argümanlar) çoğuna (tümü olmasa da) sahip olan bir nesneyi kullanır. Sorumluluk Zinciri, Koleksiyon ve tanımladığınız Boru Hattı modeli gibi diğer tasarım modellerinde kullanılabilen basit bir modeldir. Temsilcileriniz tarafından sağlanan "tür sözleşmesi" başka bir model, Arayüz.
Huperniketes

50

Stratejiler algoritmaları kapsar. Komutlar, göndereni bir talebin alıcısından ayırır, bir talebi bir nesneye dönüştürürler.

Eğer bir algoritma ise, bir şeyler nasıl yapılacaksa, bir Strateji kullanın. Bir yöntemin çağrısını yürütmesinden ayırmanız gerekirse, bir Komut kullanın. Komutlar, genellikle bir görev veya işlem gibi iletileri daha sonra kullanmak üzere sıraya koyduğunuzda kullanılır.


bu mantıklıydı en.wikipedia.org/wiki/Command_Pattern istemcisi ve invoker bağlı, ancak aynı zamanda birbirlerini bilmiyorlar!
Kalpesh Soni

26

Çok eski bir soruyu cevaplamak. (En çok oylananlar yerine en son yanıtları gören var mı?)

Benzerliklerinden dolayı olması geçerli bir kafa karışıklığıdır. Hem Strateji hem de Komut kalıpları kapsüllemeyi kullanır . Ancak bu onları aynı yapmaz.

Temel fark, neyin kapsüllendiğini anlamaktır . Her iki modelin de bağlı olduğu OO ilkesi, neyin değiştiğini Kapsülle'dir .

Strateji durumunda değişen şey algoritmadır . Örneğin, bir strateji nesnesi XML dosyasına nasıl çıktı verileceğini bilirken, diğeri JSON'a çıktı verir. Farklı sınıflarda farklı algoritmalar tutulur ( kapsüllenir ). Bu kadar basit.

Komut durumunda değişen şey, talebin kendisidir. İstek, File Menu > Deleteveya Right Click > Context Menu > Deleteveya olabilir Just Delete Button pressed. Her üç durum da aynı tipte 3 komut nesnesi oluşturabilir. Bu komut nesneleri yalnızca 3 silme isteğini temsil eder; silme algoritması değil. İstekler artık nesneler olduğundan, onları kolayca yönetebiliyoruz. Aniden, geri alma veya yineleme gibi işlevler sağlamak önemsiz hale geldi.

Komutun istenen mantığı nasıl uyguladığı önemli değildir. Execute () çağrıldığında, silmeyi tetiklemek için bir algoritma uygulayabilir veya hatta onu diğer nesnelere delege edebilir, hatta bir stratejiye delege edebilir. Bu, komut modelinin yalnızca uygulama ayrıntısıdır. Bu nedenle , talep etmenin kibar bir yolu olmasa da komut olarak adlandırılmıştır : -)

Bunu strateji ile karşılaştırın; bu model yalnızca yürütülen gerçek mantıkla ilgilidir . Bunu yaparsak, minimum sınıf kümesiyle farklı davranış kombinasyonları elde etmeye yardımcı olur ve böylece sınıf patlamasını önler.

Bence, Command, kapsülleme ve polimorfizmin doğal kullanımını sağlarken, Command, kapsülleme anlayışımızı genişletmemize yardımcı oluyor.


15

Benim baktığım şekilde, aynı şeyi yapmanın birden fazla yolu var, bunların her biri bir stratejidir ve çalışma zamanında bir şey hangi stratejinin yürütüleceğini belirler.

Belki önce StrategyOne'ı deneyin, sonuçlar yeterince iyi değilse StrategyTwo'yu deneyin ...

Komutlar, TryToWalkAcrossTheRoomCommand gibi olması gereken farklı şeylere bağlıdır. Bu komut, herhangi bir nesnenin odada yürümeye çalıştığı her seferinde çalıştırılacaktır, ancak odanın içinde, odada yürümeye çalışmak için StrategyOne ve StrategyTwo deneyebilir.

işaret


2
RE: "aynı şeyi yapmanın birden fazla yolu" - Bu, bazı yaygın Strateji örnekleriyle çelişiyor gibi görünüyor. Özellikle toplama, çıkarma, çarpma vb. Yapan uygulama sınıflarının olduğu yerler. Belki bunlar iyi örnekler değildir?
Joshua Davis

1
@JoshuaDavis tüm bu "substratlar" tek bir stratejinin özel durumlarıdır: aritmetik işlem . ortak argümanlar (2 işlenen) vardır ve sonuç olarak bir değer üretirler. uygulamaya bağlı olarak hemen hemen aynı şeyi (kara kutu olarak) kendi farklı yöntemleriyle yapmak. bu yüzden burada bir çatışma görmüyorum, ama tam tersi: güzel örnek =)
jungle_mole

7

Bence yanılıyor olabilirim, ancak komuta yürütülecek işlev veya tepki olarak davranıyorum . En az iki oyuncu olmalıdır: eylemi talep eden ve eylemi gerçekleştiren kişi. GUI, komut kalıbı için tipik bir örnektir:

  • Uygulama araç çubuğundaki tüm düğmeler bazı eylemlerle ilişkilidir.
  • Button, bu durumda uygulayıcıdır.
  • Eylem, bu durumda komuttur.

Komut genellikle belirli bir kapsam veya iş alanıyla sınırlıdır, ancak gerekli değildir: execute()bir uygulama içinde bir fatura düzenleyen, bir roket başlatan veya aynı arayüzü uygulayan bir dosyayı (örn. Tek yöntem) kaldıran komutlarınız olabilir . Genellikle komutlar kendi kendini içerir, bu nedenle yürütmek istedikleri görevi işlemek için uygulayıcıdan herhangi bir şeye ihtiyaç duymazlar (gerekli tüm bilgiler yapım sırasında verilir), bazen komutlar içeriğe duyarlıdır ve bu bağlamı keşfedebilmelidir. ( Backspace komutu, önceki karakteri doğru bir şekilde kaldırmak için metindeki düzeltme işaretinin konumunu bilmelidir; Geri alma komutu, geri alınacak geçerli işlemi keşfetmelidir; ...).

Strateji biraz farklı: daha bazı alana bağlıdır. Strateji, bir tarihi biçimlendirmek (UTC'ye özgü yerel ayarda?) ("Tarih biçimlendirici" stratejisi) veya geometrik bir şekil için bir kare hesaplamak ("kare hesap makinesi" stratejisi) için bir kural tanımlayabilir. Stratejiler bu anlamda, bir şeyi girdi olarak alan ("tarih", "şekil", ...) ve onun temelinde bazı kararlar veren uçucu ağırlık nesneleridir. Belki de strateji iyi değil, fakat iyi bir örnek ile bağlantılı biridir javax.xml.transform.Sourcearayüz: geçirilen nesne olup olmadığına bağlı olarak DOMSourceya da SAXSourceveya StreamSourcestratejisi (= XSLT transformatör bu durumda) işlemek için farklı kurallar uygulanacaktır. Uygulama basit olabilir switchveya sorumluluk zinciri modelini içerebilir .

Ama aslında bu iki model arasında ortak bir nokta var: komutlar ve stratejiler, aynı anlamsal alan içindeki algoritmaları kapsıyor.


1
Komutu bir geri arama işlevi veya tepki olarak ele alıyorum. En az iki oyuncu olmalı: biri eylemi talep eden ve diğeri uygulayan ... - Ne demeye çalıştığınızı anlıyorum, ancak 'geri arama' kelimesini kullanmaktan çekiniyorum çünkü çoğu zaman 'geriçağırım' eşzamansız bir çağrı anlamına gelir ve komut kalıbının kullanışlı olması için eşzamansız çağrılar yapmanıza gerek yoktur. Örnek olay: Microsoft Word. Araç çubuğu düğmesi tıklamaları ve kısayol tuşu basışları eşzamansız komutları çağırmaz, ancak bu durumda komut kalıbının nasıl yararlı olacağını takdir edebiliriz
Jim G.

Katılıyorum, ancak Jim'in dediği gibi geri arama referansını kaldırmak için düzenleme yapacağım.
JARC

Teşekkürler, bazı uzantılar yaptım. Kabul ediyorsanız / katılmıyorsanız bana bildirin.
dma_k

5

Komut:

Temel bileşenler:

  1. Komut gibi soyut komutlar için bir arayüz bildirirexecute()
  2. Alıcı , belirli bir komutu nasıl yürüteceğini bilir
  3. Invoker ,yürütülmesi gereken ConcreteCommand'e sahiptir
  4. Müşteri , ConcreteCommand'ı oluştururve Alıcıyı atar
  5. ConcreteCommand , Komut ve Alıcı arasındaki bağlantıyı tanımlar

İş Akışı:

İstemci , Invoker => Invoker'ı çağırır ConcreteCommand => ConcreteCommand , soyut Command yöntemini uygulayan Receiver yöntemini çağırır .

Avantaj : İstemci, Komut ve Alıcıdaki değişikliklerden etkilenmez. Invoker, Müşteri ve Alıcı arasında gevşek bağlantı sağlar. Aynı Invoker ile birden fazla komut çalıştırabilirsiniz.

Komut kalıbı,aynı Çağırıcıyı kullanarakfarklı Alıcılar üzerinde bir komut yürütmenizi sağlar. Invoker, Alıcının türünün farkında değil

Kavramların daha iyi anlaşılması için, bu JournalDev bir göz makalesinde tarafından Pankaj Kumar ve DZone makalesinde tarafından James Sugrue Vikipedi bağlantısına ek olarak.

Sen kullanabilirsiniz Komut için desen

  1. Çağırıcıyı ve komut alıcısını ayırın

  2. Geri arama mekanizmasını uygulayın

  3. Geri alma ve yineleme işlevini uygulayın

  4. Komutların geçmişini koruyun

java.lang.ThreadKomut kalıbının iyi bir uygulamasıdır . Sen davranabilirsiniz Konu invoker & sınıfta uygulama olarak Runnable olarak ConcreteCommonad / Alıcı ve run()olarak yöntemiyle Komutanlığı .

Komut modelinin Geri Al / Yinele versiyonu Theodore Norvell'in makalesinde okunabilir.

Strateji:

Strateji kalıbının anlaşılması çok basittir. Bu modeli ne zaman kullanın

Bir algoritma için birden fazla uygulamanız var ve algoritma uygulaması, belirli koşullara bağlı olarak çalışma zamanında değişebilir .

Havayolu rezervasyon sisteminin Ücret bileşeninin bir örneğini ele alalım

Havayolları, farklı zaman dilimlerinde - Yoğun ve Yoğun Olmayan aylarda farklı Ücretler sunmak ister. Yoğun olmayan seyahat günlerinde, cazip indirimler sunarak talebi canlandırmak istiyor.

Strateji modelinin temel çıkarımları :

  1. Bu davranışsal bir kalıp
  2. Yetkilendirmeye dayalıdır
  3. Yöntem davranışını değiştirerek nesnenin cesaretini değiştirir
  4. Algoritma ailesi arasında geçiş yapmak için kullanılır
  5. Çalışma zamanında nesnenin davranışını değiştirir

Kod örnekleriyle ilgili gönderiler:

Command Design modelini kullanma

Strateji Modelinin Gerçek Dünyadan Örneği


0

Benim için fark, niyetten kaynaklanıyor. Her iki modelin uygulamaları oldukça benzerdir, ancak farklı amaçları vardır:

  • Bir Strateji için, nesneyi kullanan bileşen, nesnenin ne yaptığını bilir (ve onu kendi işinin bir bölümünü gerçekleştirmek için kullanır), ancak nasıl yaptığı umurunda değildir .

  • Bir Komut için, nesneyi kullanan bileşen , Komutun ne yaptığını veya nasıl yaptığını bilmez - sadece onu nasıl çağıracağını bilir. Arayanın görevi sadece komutu çalıştırmaktır - Komuta tarafından gerçekleştirilen işlem, arayanın temel işinin bir parçasını oluşturmaz.

Aradaki fark budur - bileşeni kullanan nesne, bileşenin ne yaptığını gerçekten biliyor mu veya önemsiyor mu? Çoğu zaman bu, desen nesnesinin çağırıcısına bir değer döndürüp döndürmediğine bağlı olarak belirlenebilir. Çağıran, desen nesnesinin ne yaptığını umursuyorsa, muhtemelen bir şey döndürmesini isteyecektir ve bu bir Strateji olacaktır. Herhangi bir dönüş değeri umursamıyorsa, muhtemelen bir Komuttur (not, Java Çağrılabilir gibi bir şey hala bir Komuttur, çünkü bir değer döndürmesine rağmen arayan değeri umursamaz - sadece geri gönderir Komutu orijinal olarak sağladıysa).

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.