Birinci sınıf işlevler Strateji modelinin yerine geçiyor mu?


15

Strateji tasarım deseni sık sık yoksun dilde birinci sınıf işlevleri için bir yedek olarak kabul edilir.

Örneğin, işlevselliği bir nesneye geçirmek istediğinizi varsayalım. Java'da, istenen davranışı kapsayan başka bir nesneyi nesneye iletmeniz gerekir. Ruby gibi bir dilde, işlevselliğin kendisini anonim bir işlev biçiminde geçirirsiniz.

Ancak bunu düşünüyordum ve belki de Strateji'nin basit bir anonim işlevden fazlasını sunduğuna karar verdim.

Bunun nedeni, bir nesnenin, yöntemin çalıştığı dönemden bağımsız olarak var olan durumu tutabilmesidir. Ancak anonim bir işlev, yalnızca işlevin yürütülmesi bittiğinde varolmayan durumu tutabilir.

Birinci sınıf işlevleri destekleyen nesne yönelimli bir dilde, strateji modelinin işlevleri kullanmaya göre herhangi bir avantajı var mı?


10
"Ancak anonim bir işlev, yalnızca işlev yürütmeyi bitirdiğinde varolmayan bir durumu tutabilir.": Bu doğru değil: bir kapatma, farklı çağrılarda yaşayan durumu tutabilir.
Giorgio

"Ancak anonim bir işlev, yalnızca işlevin yürütülmesi bittiğinde varolmayan durumu tutabilir." : global değişkenleri ve en azından statik değişkenleri unutmamak.
gbjbaanb

Yanıtlar:


13

Dil işleve referansları desteklediğinde ( Java sürüm 8'den bu yana ), bunlar genellikle stratejiler için iyi bir alternatiftir, çünkü genellikle aynı şeyi daha az sözdizimi ile ifade ederler. Bununla birlikte, gerçek bir nesnenin yararlı olabileceği bazı durumlar vardır.

Bir Strateji arabiriminin birden çok yöntemi olabilir. RouteFindingStragegyÖrnek olarak, farklı rota bulma algoritmalarını kapsayan bir arayüz alalım . Gibi yöntemler ilan edebilir

  • Route findShortestRoute(Node start, Node destination)
  • boolean doesRouteExist(Node start, Node destination)
  • Route[] findAllPossibleRoutes(Node start, Node destination)
  • Route findShortestRouteToClosestDestination(Node start, Node[] destinations)
  • Route findTravelingSalesmanRoute(Node[] stations)

bu da hepsi strateji tarafından uygulanacaktı. Bazı rota bulma algoritmaları, bu kullanım senaryolarının bazıları için dahili optimizasyonlara izin verebilir ve bazıları olmayabilir, bu nedenle uygulayıcı bu yöntemlerin her birinin nasıl uygulanacağına karar verebilir.

Diğer bir durum, stratejinin içsel bir durumu olduğu zamandır. Elbette, bazı dillerde kapaklar içsel duruma sahip olabilir, ancak bu iç durum çok karmaşıklaştığında, tam teşekküllü bir sınıfa kapanmayı teşvik etmek genellikle daha zarif hale gelir.


2
“Bu iç durum çok karmaşıklaştığında, tam teşekküllü bir sınıfa kapanmayı teşvik etmek genellikle yararlı olur”: Neden? İç durum karmaşık hale gelirse, kapağın içinde saklanan bir nesneye / kayda da koyabilirsiniz.
Giorgio

1
@Giorgio Ama sonra iki sözdizimi varlığınız olur - kapanış ve iç durumunu yöneten sınıf. Böylece kod, kapatmayı bu sınıfa taşıyarak basitleştirilebilir. Bu daha iyi olabilir veya tam olarak kullanım durumuna, programlama diline ve kişisel tercihinize bağlı olabilir.
Philipp

Bana mantıklı geliyor.
Giorgio

5

Anonim bir işlevin yalnızca işlev yürütmeyi bitirdiğinde sona eren durumu tutabileceği doğru değildir.

Common Lisp'de aşağıdaki örneği alın:

(defun number-strings (ss)
  (let ((counter 0))
    (mapcar #'(lambda (s) (format nil "~a: ~a" (incf counter) s)) ss)))

Bu işlev bir dize listesi alır ve listenin her öğesine bir sayaç ekler. Yani, örneğin,

(number-strings '("a" "b" "c"))

verir

("1: a" "2: b" "3: c")

İşlev number-stringsdahili olarak counter, işlev her çağrıldığında yeniden kullanılan durumu (sayacın geçerli değeri) tutan bir değişkenle anonim bir işlev kullanır .

Genel olarak, kapatmayı tek bir yöntemle bir nesne olarak düşünebilirsiniz. Alternatif olarak, bir nesne aynı kapalı değişkenleri paylaşan bir kapak koleksiyonudur. Bu yüzden, kapanış yerine bir nesneyi kullanmanız gereken durumlar olup olmadığından emin değilim: Her ikisinin de aynı kalıba farklı bakış açılarından bakmanın yolları olduğunu iddia ediyorum.

Özellikle, strateji modeli yalnızca bir yöntemle bir nesne gerektirir, bu nedenle bir kapatma işi yapmalıdır. Ancak, Philipp'in cevabında gözlemlediği gibi, koşullara (karmaşık durum) ve programlama dillerine bağlı olarak nesneleri kullanarak daha zarif bir çözüm elde edebilirsiniz.


Yani birinci sınıf işlevleri kapanış olarak destekleyen bir dilde, hala 'klasik' Stratejiyi kullanır mıydınız?
Aviv Cohn

1
Philipp ile hemfikirim: dile ve kişisel tercihlere bağlı. Notasyonu her zaman mümkün olduğunca basitleştiren yaklaşımı seçerdim. Örneğin, Lisp'de durumumu bir değişkenler listesi olarak lettanımlayabilirim ve sonra içindeki kapatmamı tanımlayabilirim. Temel olarak, anında bir yöntemle bir nesne tanımlardım. Başka bir dilde (örn. Java), durumu tutmak için uygun bir nesne tanımlamak daha uygun (sözdizimsel olarak daha basit) olabilir. Yani, durumdan duruma karar verirdim.
Giorgio

1

İki tasarımın aynı sorunu çözebilmesi, birbirlerinin doğrudan ikameleri oldukları anlamına gelmez.

İşlevsel bir programdaki durumu izlemeniz gerekiyorsa, dil izin verse bile kapalı bir değişkeni değiştirmezsiniz. Bir durumu bağımsız değişken olarak alan ve yeni durumu döndürme değeri olarak döndüren bir işlevi çağırmayı ayarlarsınız.

Mimariniz çok farklı görünecek, ancak aynı hedefe ulaşacaksınız. Bir paradigmanın desenlerini doğrudan diğerine zorlamaya çalışmayın.


"İşlevsel bir programda durumu izlemeniz gerekiyorsa, dil izin verse bile kapalı bir değişkeni değiştirmezsiniz.": Ben tamamen işlevsel bir stil hayranıyım ve tavsiyelerinize katılıyorum. Öte yandan, kapaklar sadece işlevsel olmakla birlikte, sadece işlevsel bir yapı değildir. Sözcüksel bağlamdan değişkenlerin kapatılması fikri referans şeffaflığı / değişmezliği ile diktir.
Giorgio

Üzgünüm, ama tartışmanızı takip edemiyorum. Tamamen işlevsel programlamada durum işlemenin eldeki soru ile ne ilgisi var?
Philipp

1
Mesele şu ki, birinci sınıf işlevler gibi işlevsel bir paradigmanın bir kısmını kullanırsanız, düzgün çalışmasını sağlamak için paradigmanın diğer bölümlerini çekmeniz gerekiyorsa şaşırmayın.
Karl Bielefeldt

1

Strateji bir kavram , belirli ve tekrar eden bir sorunu çözmek için kullanışlı bir reçetedir. Bu bir dil kurumu değil, herhangi bir uygulama şekliyle de ilgili değildir . Kapatma, bir gün Strateji ve ertesi gün Gözlemci uygulamak için kullanılabilir.

Terim Strateji kısaca sizin niyet ifade etmek diğer programcılar ile konuşmaları çoğunlukla yararlıdır. Bunda büyülü bir şey yok.


2
Soru, spesifik olarak belirli bir sınıf yapısına sahip olan strateji tasarım modelinden bahseder . Belirli bir amacı gerçekleştirmeyi amaçlayan bir eylem planı olarak “strateji” nin diğer anlamı bu bağlamda yanlıştır.

@Snowman ile anlaşmaya meyilliyim. Strateji modelinden bahsettiğinizden emin misiniz ?
Rowan Freeman

1
@Snowman, bağlandığınız sayfa bile bu kalıbın nasıl uygulanacağını tam olarak belirtmiyor, bunun yerine belirli dillerde örnekler veriyorlar, ancak UML diyagramında C ++ mirasını, Java arayüzlerini veya Ruby bloklarını kullanmam gerektiğini söyleyen hiçbir şey yok . Bu yüzden analizinize katılmıyorum.
idoby
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.