Strateji modeli ile Bağımlılık Enjeksiyonu arasındaki fark nedir?


96

Strateji modeli ve Bağımlılık Enjeksiyonu, nesneleri çalışma zamanında ayarlamamıza / enjekte etmemize izin verir. Strateji modeli ile Bağımlılık Enjeksiyonu arasındaki fark nedir?


Strateji modeli Bağımlılık Enjeksiyonu kullanabilir
TechWisdom

Yanıtlar:


110

DI ve Strateji aynı şekilde çalışır, ancak Strateji daha ince taneli ve kısa süreli bağımlılıklar için kullanılır.

Bir nesne "sabit" bir Strateji ile yapılandırıldığında, örneğin nesne inşa edildiğinde, Strateji ve DI arasındaki ayrım bulanıklaşır. Ancak bir DI senaryosunda, nesnelerin bağımlılıklarının yaşamları boyunca değişmesi daha olağandışıdır, ancak bu Strateji ile alışılmadık bir durum değildir.

Ayrıca, ilgili yöntem argüman enjeksiyonu kavramı yaygın değildir ve çoğunlukla yalnızca otomatik test bağlamında kullanılırken stratejileri yöntemlere argüman olarak aktarabilirsiniz.

Strateji, amaca odaklanır ve sizi aynı davranış sözleşmesine uyan farklı uygulamalarla bir arayüz oluşturmaya teşvik eder. DI daha çok bazı davranışların uygulanmasına sahip olmak ve bunu sağlamakla ilgilidir.

DI ile programınızı sadece uygulamanın parçalarını değiştirebilmekten başka nedenlerle ayrıştırabilirsiniz. DI'da yalnızca bir uygulama ile kullanılan bir arayüz çok yaygındır. Yalnızca tek bir somut uygulamaya (şimdiye kadar) sahip bir "Strateji" gerçek bir sorun değildir ancak muhtemelen DI'ye daha yakındır.


DI'da sadece bir uygulama ile kullanılan bir arayüz çok yaygındır - öyleyse bu özel durumda DI nedir?
Kalpesh Soni

3
Bu alıntı temelde her şeyi açıklıyor:in a DI scenario it is more unusual that the dependencies of objects change during their lifetimes, while this is not uncommon with Strategy
Sergey Telshevsky

Strateji: Sınıflar, çalışma zamanında bir algoritma ile yapılandırılabilecek şekilde tasarlanmıştır. DI: Bu tür sınıflar, çalışma zamanında enjekte edilen bir algoritma (bir Strateji nesnesi) alır. W3sdesign.com adresindeki GoF Design Patterns Belleğinden .
GFranke

39

Aradaki fark, başarmaya çalıştıkları şeydir. Strateji kalıbı, uygulamaları değiş tokuş etmek istediğinizi bildiğiniz durumlarda kullanılır. Örnek olarak, verileri farklı şekillerde biçimlendirmek isteyebilirsiniz - strateji kalıbını bir XML biçimlendiriciyi veya CSV biçimlendiriciyi vb. Değiştirmek için kullanabilirsiniz.

Bağımlılık Ekleme, kullanıcının çalışma zamanı davranışını değiştirmeye çalışmaması bakımından farklıdır. Yukarıdaki örneği takip ederek, bir XML formatlayıcı kullanan bir XML dışa aktarma programı oluşturuyor olabiliriz. Kodu şu şekilde yapılandırmak yerine:

public class DataExporter() {
  XMLFormatter formatter = new XMLFormatter();
}

yapıcıda biçimlendiriciyi 'enjekte edersiniz':

public class DataExporter {
  IFormatter formatter = null;

  public DataExporter(IDataFormatter dataFormatter) {
    this.formatter = dataFormatter;
  }
}

DataExporter exporter = new DataExporter(new XMLFormatter());

Bağımlılık Enjeksiyonu için birkaç gerekçe vardır, ancak birincil olan test içindir. Bir çeşit kalıcılık motorunuzun olduğu bir durumunuz olabilir (bir veritabanı gibi). Bununla birlikte, testleri tekrar tekrar çalıştırırken gerçek bir veritabanı kullanmak zor olabilir. Yani, test senaryolarınız için sahte bir veritabanı enjekte edersiniz, böylece bu ek yüke maruz kalmazsınız.

Bu örneği kullanarak farkı görebilirsiniz: Her zaman bir veri depolama stratejisi kullanmayı planlıyoruz ve bu bizim aktardığımız şey (gerçek DB örneği). Bununla birlikte, geliştirme ve testte farklı bağımlılıklar kullanmak istiyoruz, bu yüzden farklı somutlar enjekte ediyoruz.


28

DI'yi bir strateji modeli olarak kullanabilirsiniz, böylece her müşteri için gerekli olan algoritmayı değiştirebilirsiniz, ancak DI bunun ötesine geçebilir, çünkü bu, bir uygulamanın parçası olmayacak şekilde bir uygulamanın parçalarını ayırmanın bir yolu olduğu için strateji kalıbı.

DI'nin sadece yeniden adlandırılmış bir strateji modeli olduğunu söylemek riskli olacaktır çünkü bu, strateji modelinin gerçekte ne için olduğunu, IMO'yu sulandırmaya başlar.


2
Sanırım özünü anlıyorum, ama bunu kelimelere tam olarak yerleştiremiyorum ... Yani senin DI daha çok bir uygulama modeli, strateji ise daha çok bir tasarım kalıbı ve stratejiyi uygulamanın bir yolu da DI üzerinden mi?
Robert Gould

1
Kulağa güzel bir ifade gibi geliyor. DI, bir strateji modelinden daha fazlasıdır. AOP ile aynı karışıklığı, insanların bunun bir fabrika modeli olduğunu düşündükleri yerde buldum. Bence DI strateji modelini uygulayabilir, bu yüzden yeniden yazmanız harika görünebilir. :)
James Black

15

Dostum, bağımlılık enjeksiyonu daha genel bir kalıptır ve somutlara değil soyutlamalara bağımlılıkla ilgilidir ve bu her kalıbın bir parçasıdır, ancak Strateji modeli daha spesifik bir soruna çözümdür.

bu, wikipedia'daki tanımdır:

DI:

Nesne yönelimli bilgisayar programlamasında bağımlılık enjeksiyonu (DI), davranışı bağımlılık çözümünden ayırmanın temel ilkesine sahip bir tasarım modelidir. Başka bir deyişle: yüksek oranda bağımlı yazılım bileşenlerini ayırmak için bir teknik.

Strateji Modeli:

Bilgisayar programlamasında, strateji modeli (politika modeli olarak da bilinir), algoritmaların çalışma zamanında seçilebildiği belirli bir yazılım tasarım modelidir.

Strateji modelinin, bir algoritma ailesi tanımlamak, her birini bir nesne olarak kapsüllemek ve bunları birbirinin yerine geçebilir hale getirmek için bir araç sağlaması amaçlanmıştır. Strateji modeli, algoritmaların onları kullanan istemcilerden bağımsız olarak değişmesine izin verir.


4
Açıklamanızdaki "ahbap" kısmını özellikle beğendim. :-)
johey

7

Stratejiler, işlerin nasıl hesaplandığını değiştirmek için kullanılan üst düzey şeylerdir. Bağımlılık enjeksiyonu ile sadece işlerin nasıl hesaplandığını değil, aynı zamanda orada olanı da değiştirebilirsiniz.

Benim için birim testleri kullanıldığında netleşiyor. Üretim kodunun yürütülmesi için, tüm verileriniz gizlidir (yani özel veya korumalı); oysa, birim testleri ile, verilerin çoğu herkese açık olduğundan, Asserts ile ona bakabilirim.


Strateji örneği:

public class Cosine {
  private CalcStrategy strat;

  // Constructor - strategy passed in as a type of DI
  public Cosine(CalcStrategy s) {
    strat = s;
  }
}

public abstract class CalcStrategy {
  public double goFigure(double angle);
}

public class RadianStrategy extends CalcStrategy {
  public double goFigure(double angle) {
    return (...);
  }
}
public class DegreeStrategy extends CalcStrategy {
  public double goFigure(double angle) {
    return (...);
  }
}

Stratejiler arasında farklı olan herkese açık veri bulunmadığına dikkat edin. Farklı yöntemler de yok. Her iki strateji de aynı işlevleri ve imzaları paylaşır.


Şimdi bağımlılık enjeksiyonu için:

public class Cosine {
  private Calc strat;

  // Constructor - Dependency Injection.
  public Cosine(Calc s) {
    strat = s;
  }
}

public class Calc {
  private int numPasses = 0;
  private double total = 0;
  private double intermediate = 0;

  public double goFigure(double angle) {
    return(...);
}

public class CalcTestDouble extends Calc {
  // NOTICE THE PUBLIC DATA.
  public int numPasses = 0;
  public double total = 0;
  public double intermediate = 0;
  public double goFigure(double angle) {
    return (...);
  }
}

Kullanım:

public CosineTest {

  @Test
  public void testGoFigure() {
    // Setup
    CalcTestDouble calc = new CalcTestDouble();
    Cosine instance = new Cosine(calc);

    // Exercise
    double actualAnswer = instance.goFigure(0.0);

    // Verify
    double tolerance = ...;
    double expectedAnswer = ...;
    assertEquals("GoFigure didn't work!", expectedAnswer,
         actualAnswer, tolerance);

    int expectedNumPasses = ...;
    assertEquals("GoFigure had wrong number passes!",
        expectedNumPasses, calc.numPasses);

    double expectedIntermediate = ...;
    assertEquals("GoFigure had wrong intermediate values!",
        expectedIntermediate, calc.intermediate, tolerance);
  }
}

Son 2 kontrole dikkat edin. Test edilen sınıfa enjekte edilen test çiftindeki halka açık verileri kullandılar. Veri gizleme prensibi nedeniyle bunu üretim kodu ile yapamadım. Üretim koduna özel amaçlı test kodunun eklenmesini istemedim. Herkese açık verilerin farklı bir sınıfta olması gerekiyordu.

Çift test enjekte edildi. Bu, yalnızca işlevleri değil verileri etkilediği için bir stratejiden farklıdır .


4

Bağımlılık enjeksiyonu, kısaca açıklayacağım strateji modelinin iyileştirilmesidir. Genellikle çalışma zamanında birkaç alternatif modül arasında seçim yapmak gerekir. Bu modüllerin tümü, birbirlerinin yerine kullanılabilmeleri için ortak bir arayüz uygular. Strateji modelinin amacı, karar verme sürecini strateji nesnesi olarak adlandıracağım ayrı bir nesneye kapsülleyerek hangi modüllerin kullanılacağına (yani hangi "somut strateji" veya bağımlılık) karar verme yükünü ortadan kaldırmaktır.

Bağımlılık enjeksiyonu, yalnızca hangi somut stratejinin kullanılacağına karar vermekle kalmaz, aynı zamanda somut stratejinin bir örneğini yaratarak ve onu çağıran modüle "enjekte ederek" strateji modelini geliştirir. Somut strateji örneğinin nasıl yönetileceğine (başlatılacağına vb.) İlişkin bilgi strateji nesnesinin içinde de gizlenebileceğinden, bu yalnızca tek bir bağımlılık olsa bile yararlıdır.


1

Aslında, bağımlılık enjeksiyonu da Bridge modeline çok benziyor. Bana göre (ve tanıma göre), Köprü modeli uygulamanın farklı versiyonlarını barındırırken , Strateji modeli tamamen farklı mantık içindir. Ancak örnek kod, DI kullanıyor gibi görünüyor. Öyleyse belki DI sadece bir teknik veya uygulama mı?


0

Strateji, bağımlılık ekleme becerilerinizi kullanmak için bir arenadır. Bağımlılık ekleme uygulamasının gerçek yolları aşağıdaki gibidir: -

  1. Etkinlikler
  2. Birlik / yapı haritası (veya programlı olarak) vb. Konfigürasyon dosyaları
  3. Uzatma Yöntemleri
  4. Soyut fabrika modeli
  5. Kontrol modelinin tersine çevrilmesi (hem strateji hem de Soyut Fabrika tarafından kullanılır)

Yine de, stratejiyi ayrı kılan bir şey var. Unity'de bildiğiniz gibi uygulama başladığında tüm bağımlılıklar ayarlanmıştır ve daha fazla değiştiremeyiz. Ancak strateji, çalışma zamanı bağımlılık değişikliğini destekler. Ancak Stratejinin sorumluluğunu değil, bağımlılığı yönetmeli / enjekte etmeliyiz!

Aslında strateji, bağımlılık enjeksiyonundan bahsetmez. Gerekirse, bir Strateji kalıbı içinde Soyut Fabrika aracılığıyla yapılabilir. Strateji yalnızca arayüzlü bir sınıflar ailesi oluşturmaktan ve onunla 'oynamaktan' bahsediyor. Oynarken, sınıfların farklı bir aşamada olduğunu fark edersek, o zaman onu kendimize enjekte etmemiz gerekir, ancak Stratejinin işi değil.


0

SOLID ilkelerini dikkate alırsak - Açık Kapalı İlke için Strateji Modeli ve Bağımlılık Tersine Çevirme İlkesi için Bağımlılık Enjeksiyonu kullanıyoruz


1
Takip ettiğimden emin değilim, Stratejinin Açık / Kapalı ilkesiyle nasıl bir ilişkisi olduğunu ve DIP ile DIP ile nasıl bir ilişkisi olduğunu açıklar mısınız?
Adam Parkin
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.