Strateji modeli ve bağımlılık enjeksiyonunu kullanarak kalıtımın yerini tamamen alabilir miyiz?


10

Örneğin:

var duckBehaviors = new Duckbehavior();
duckBehaviors.quackBehavior = new Quack();
duckBehaviors.flyBehavior = new FlyWithWings();
Duck mallardDuck = new Duck(DuckTypes.MallardDuck, duckBehaviors)

Duck sınıfı tüm davranışları (soyut) içerdiğinden, MallardDuck(genişleten Duck) yeni bir sınıf oluşturmak gerekli görünmemektedir.

Referans: İlk Baş Tasarım Deseni, Bölüm 1.


Duckbehavior.quackBehaviorKodunuzdaki türleri ve diğer alanları nedir?
max630

Örneğinizde bağımlılık enjeksiyonu yoktur.
David Conrad

11
Miras harika bir orta ila orta seviye geliştiriciniz olduğunda harika çünkü etrafta hileler ve tasarım desenleri uzun bir geçmişi var. Ancak en deneyimli geliştiriciler, mümkün olduğunca kompozisyona dayalı gerçekten sığ miras hiyerarşilerini tercih etmek için konuştum. Kalıtım gerekenden daha sıkı bağlantıya neden olabilir ve değişiklikleri zorlaştırabilir.
Mark Rogers


5
@DavidConrad: OP sınıfta yeni bir şey yapmıyor . DI / IoC, konteynırlar hakkında değil , asla "yeni" kullanmama konusunda bağımlılıkları enjekte etmektir ; bu tamamen dik bir kaygı. Ayrıca, her zaman kodu bir yerde değiştirmeniz gerekir - bu kompozisyon kökü veya bazı yapılandırma dosyasıdır. Bağımlılıkların yaratılmasını kontrol eden şey Duck kralı değil, bazı dış bağlamlar olduğu için kontrol burada Duck tipi içinde ters çevrilir ; Bu, açıklık için verilen bir oyuncak örneğidir, dış bağlamın sadece arama kodu ile temsil edilmesi gayet iyidir.
Filip Milovanović

Yanıtlar:


21

Tabii, ama biz buna kompozisyon ve yetki diyoruz . Strateji Düzeni ve Bağımlılık Enjeksiyonu yapısal olarak benzer görünebilir, ancak amaçları farklıdır.

Strateji Kalıbı , aynı arabirim altında davranışların çalışma zamanında değiştirilmesine izin verir. Bir yeşilbaş ördeğe uçmasını ve kanatlarla uçmasını izleyebilirim. Sonra bir jet pilot ördeği için değiştirin ve Delta havayolları ile uçmasını izleyin. Program çalışırken bunu yapmak bir Strateji Kalıbı meselesidir.

Bağımlılık Enjeksiyonu , sabit kodlama bağımlılıklarından kaçınmak için bir tekniktir, böylece müşterilerin değiştiklerinde değiştirilmesini gerektirmeden bağımsız olarak değişebilirler. Müşteriler ihtiyaçlarını nasıl karşılayacaklarını bilmeden basitçe ifade ederler. Böylece nasıl karşılandıklarına başka bir yerde karar verilir (tipik olarak ana). Bu tekniği kullanmak için iki ördeğe ihtiyacınız yok. Hangi ördeği bilmeden veya umursamadan ördek kullanan bir şey. Ördek inşa etmeyen ya da aramaya gitmeyen ama elindeki ördekleri kullanmaktan çok mutlu olan bir şey.

Eğer somut bir ördek sınıfım varsa, onun sinek davranışını uygulayabilir. Hatta bir durum değişkenine dayanarak davranışları kanatlı uçmaktan Delta'ya uçmak bile isteyebilirdim. Bu değişken bir boolean, int olabilir veya bir if ile test etmek zorunda kalmadan her hangi bir uçan stili yapan FlyBehaviorbir flymetoda sahip olabilir. Şimdi ördek türlerini değiştirmeden uçan stilleri değiştirebilirim. Şimdi havuzlar pilot olabilir. Bu kompozisyon ve delegasyon . Ördek bir FlyBehavior'dan oluşur ve uçan istekleri ona devredebilir. Tüm ördek davranışlarınızı aynı anda değiştirebilir veya her davranış veya aradaki herhangi bir kombinasyon için bir şey tutabilirsiniz.

Bu size mirasın biri dışında sahip olduğu tüm güçleri verir. Kalıtım, Duck alt türlerinde hangi Duck yöntemlerini geçersiz kıldığınızı ifade etmenizi sağlar. Kompozisyon ve temsilci seçme, Duck'ın başlangıçtan itibaren alt türlere açıkça yetki vermesini gerektirir. Bu çok daha esnektir ancak daha fazla klavye yazmayı içerir ve Duck bunun olduğunu bilmelidir.

Bununla birlikte, birçok insan mirasın en baştan açıkça tasarlanması gerektiğine inanmaktadır. Ve eğer öyle değilse, mirasa izin vermemek için sınıflarınızı mühürlü / final olarak işaretlemelisiniz. Bu görüşe bakarsanız, mirasın kompozisyon ve temsilci seçime göre hiçbir avantajı yoktur. Çünkü o zaman her iki durumda da ya başlangıçtan itibaren genişletilebilirlik için tasarım yapmanız ya da daha sonra işleri parçalamak için istekli olmanız gerekir.

Şeyleri yıkmak aslında popüler bir seçenektir. Sadece sorunun olduğu durumlar olduğunu unutmayın. Bir sonraki sürümle güncellemek istemediğiniz kitaplıkları veya kod modüllerini bağımsız olarak dağıttıysanız, şu ana kadar neler yaptığınız hakkında hiçbir şey bilmeyen sınıfların sürümleriyle uğraşabilirsiniz.

Daha sonra işleri yırtmaya istekli olmak sizi tasarımdan fazla kurtarabilirken, ördek kullanıldığında ne yapacağını bilmeden bir ördek kullanan bir şey tasarlayabilme konusunda çok güçlü bir şey var. Bilmemek güçlü şeylerdir. Bir süre ördekleri düşünmeyi bırakıp kodunuzun geri kalanını düşünmenizi sağlar.

"Yapabilir miyiz" ve "yapmalıyız" farklı sorulardır. Kompozisyon Miras Üzerine İyileştirme asla miras kullanma anlamına gelmez. Hala mirasın en mantıklı olduğu durumlar var. Size en sevdiğim örneği göstereceğim :

public class LoginFailure : System.ApplicationException {}

Devralma, yalnızca bir satırda daha belirgin, açıklayıcı adlarla istisnalar oluşturmanıza olanak tanır.

Kompozisyon ile yapmayı deneyin ve bir karmaşa elde edersiniz. Ayrıca, kalıtım yo-yo problemi riski yoktur, çünkü burada kalıtım zincirini yeniden kullanmak ve teşvik etmek için veri veya yöntem yoktur. Tüm bu ekler iyi bir isim. İyi bir ismin değerini asla küçümsemeyin.


1
" İyi bir ismin değerini asla küçümsemeyin ". İmparatorun yeni kıyafet zamanı: LoginExceptioniyi bir isim değil. Klasik "şirin adlandırma" ve eğer alırsam Exception, sahip olduğum tek şey Login, bana neyin yanlış gittiğine dair hiçbir şey söylemiyor.
David Arno

Ne yazık ki biz Exceptionher istisna sınıfının sonuna koyarak saçma sözleşmesi ile sıkışmış , ama lütfen "onunla sıkışmış" ile "iyi" karıştırmayın.
David Arno

@DavidArno Daha iyi bir isim önerebilirsen ben kulaklarım. Burada mevcut bir kod tabanının kurallarına hapsolmama avantajına sahibiz. Dünyayı parmaklarınızın ucuyla değiştirme gücünüz olsaydı, ona ne isim verirdiniz?
candied_orange

Onları, isim ediyorum StackOverflow, OutOfMemory, NullReferenceAccess, LoginFailurevb Temelde, adı kapalı "durum" alır. Ve gerekirse, neyin yanlış gittiğini açıklayacak şekilde düzeltin.
David Arno

@DavidArno komutuyla.
candied_orange

7

Hemen hemen her metodolojiyi başka herhangi bir metodolojiyle değiştirebilir ve yine de çalışan bir yazılım üretebilirsiniz. Ancak bazıları belirli bir soruna diğerlerinden daha iyi uyum sağlar.

Tercih edilen birçok şeye bağlıdır. Uygulamada önceki sanat, takımdaki deneyim, gelecekteki gelişmeler, kişisel tercih ve yeni gelen birinin kafasını almasının ne kadar zor olacağını birkaç isim belirtmek.

Diğer insanların kreasyonları ile daha sık deneyimlendikçe ve daha sık mücadele ettikçe, muhtemelen son tefekküre daha fazla önem vereceksiniz.

Kalıtım hala her zaman en esnek olmayan geçerli ve güçlü bir modelleme aracıdır, ancak sorun alanına net eşleme için minnettar olabilecek yeni insanlara güçlü rehberlik sunar.


-1

Kalıtım bir zamanlar düşünüldüğü kadar önemli değildir. Hala önemlidir ve kaldırılması kötü bir hata olur.

Böylece uç bir örnek, her şey NSObject bir alt sınıfı (derleyici aslında bir baseclass sahip olmayan bir sınıf bildirmek izin vermez ise Objective-C olduğu her şey derleyici dahili olmayan bir şeyin alt sınıf olmalıdır derleyiciye yerleştirilmiş). Kaçırmak zorunda kalmayacağınız NSObject'te birçok yararlı şey var.

Bir başka ilginç örnek, iOS geliştirme için UIKit'teki temel "görünüm" sınıfı olan UIView'dir. Bu, bir yandan, alt sınıfların doldurması gereken işlevselliği bildiren soyut bir sınıf gibi bir sınıftır, ancak kendi başına da yararlıdır. Genellikle olduğu gibi kullanılan UIKit tarafından sağlanan alt sınıflara sahiptir. Bir görünümde alt görünümleri yükleyen geliştirici tarafından kompozisyon var. Ve genellikle kompozisyonu kullanan geliştirici tanımlı alt sınıflar vardır. Katı bir kural veya hatta kural yoktur, gereksinimlerinize en uygun olanı kullanırsınız.


"En uç örneğiniz" kabaca en modern OO dillerinin işleyiş typeObjectObject
şeklidir

-1

[Başsız soruya arsız bir cevap vereceğim.]

Strateji modeli ve bağımlılık enjeksiyonunu kullanarak kalıtımın yerini tamamen alabilir miyiz?

Evet ... strateji kalıbının kendisi kalıtım kullanıyor. Strateji kalıbı arayüz kalıtımı üzerinde çalışır. Kalıtımın kompozisyon + stratejisiyle değiştirilmesi, kalıtımı farklı bir yere taşır. Bununla birlikte, böyle bir değiştirme genellikle yapmaya değer, çünkü hiyerarşileri ayırmaya izin verir .


2
" Strateji kalıbı arayüz kalıtımı üzerinde çalışır ". Unutmayın, strateji kalıbı bir tasarım kalıbıdır; bir uygulama kalıbı değil. Bu yüzden arayüzler kullanılarak uygulanabilir, ancak örneğin bir karma / fonksiyon sözlüğü kullanılarak eşit olarak uygulanabilir.
David Arno

3
Arayüz mirası hiç miras değil, sadece bir sözleşme veya sınıflandırıcıdır. Temsilcileri strateji modeli için de kullanabilirsiniz (bunları kullanmayı tercih ederim).
Deepak Mishra

Artı bir, ahbap: ... arayüz kalıtım üzerinde çalışır , genel terim "arayüz" doğru kullanımı üzerine kudos. Kötü ya da yetersiz sınıf tasarımının bu sorunun ortaya çıkmasının temel nedeni olduğunu düşünüyorum. Bir kitabı neden / nasıl alacağını açıklamak; şeytan Ayrıntıda. Görmek için bir neşe ve aynı zamanda cehennem gibi derin miras tasarımları ile çalıştım. Kalıtımla interfacesabitlenmiş saçmalık tasarım gördüm . Buradaki gizli sorun, bağımlı davranışı değiştiren tutarsız bir uygulamadır. P, S. miras ve arayüz birbirini dışlayan değil,
radarbob

@ DavidArno yorumu : OP sorusuna eklenirse bu yorum iyi olur. OP sorusu teknik olarak yanlış bir şekilde ifade edilmiştir, ancak yine de anlıyoruz. Sorun bu özel cevap değil.
radarbob

@DeepakMishra comment: . Bir "arayüz" bir sınıfın herkese açık üyeleridir. Ne yazık ki "arayüz" anlamı aşırı yüklü. Genel anlamı bir programlama dilinin anahtar kelimesi ile ayırt etmeye dikkat etmeliyizinterface
radarbob

-2

Hayır. Bir yeşilbaş ördeği diğer ördek türlerinden daha farklı parametreler gerektiriyorsa, değiştirmek kabus olacaktır. Ayrıca bir ördek başlatabilir misiniz? Daha çok yeşilbaş ördek veya Mandarin ördeği ya da başka türlü ördekleriniz var.

Ayrıca bir tür hiyerarşisi daha iyi olabilir bu yüzden türleri etrafında bazı mantık isteyebilir.

Kodun yeniden kullanımı bazı işlevler için sorunlu hale gelirse, işlevleri yapıcıdan geçirerek oluşturabiliriz.

Yine, bu gerçekten sizin kullanım durumunuza bağlıdır. Sadece bir ördeğiniz ve yeşilbaş bir ördeğiniz varsa, sınıf hiyerarşisi çok daha basit bir çözümdür.

Ancak strateji modelini kullanmak istediğiniz bir örnek: Müşteri sınıflarınız varsa ve happy hour faturalandırma stratejisi veya normal faturalandırma stratejisi olabilecek bir faturalandırma stratejisine (arayüz) geçmek istiyorsanız, bunu geçebilirsiniz yapıcı. Bu şekilde iki farklı müşteri sınıfı yapmak zorunda kalmazsınız ve bir hiyerarşiye ihtiyacınız olmaz. Sadece bir müşteri sınıfına sahipsiniz.

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.