Bağımlılık Enjeksiyonu Fabrika deseni ile birlikte nasıl kullanılır


10

Herhangi bir türdeki dosyaları ayrıştırmaktan sorumlu bir modül düşünün. Zaten üzerinde açıkladığım gibi ben bu sorunu çözmek için strateji deseni kullanarak düşünüyorum burada . Bu soruya devam etmeden önce lütfen bağlantılı gönderiye bakın.

Product.xml dosyasının içeriğine ihtiyaç duyan B sınıfını düşünün. Bu sınıfın XML dosyasını ayrıştırmak için Parser arabiriminin uygun somut uygulayıcısını başlatması gerekecektir. Uygun beton uygulayıcının somutlaştırılmasını, B sınıfı "a" Fabrikası olacak şekilde bir Fabrikaya devredebilirim. Ancak, B sınıfı beton uygulayıcıyı somutlaştırmak için bir Fabrikaya "bağımlı" olacaktır. Bu, yapıcı veya B sınıfındaki bir ayarlayıcı yöntemin Fabrikadan geçirilmesi gerektiği anlamına gelir.

Bu nedenle, bir dosyayı ayrıştırması gereken Fabrika ve B sınıfı birbirine sıkı sıkıya bağlı olacaktır. Şimdiye kadar açıkladığım şeyler konusunda tamamen yanlış olabileceğimi anlıyorum. Enjekte edilecek bağımlılığın bir Fabrika olduğu bir senaryoda bağımlılık enjeksiyonunu kullanıp kullanamayacağımı ve bunu uygulamak için doğru yolun ne olacağını bilmek istiyorum.

Yanıtlar:


8

Bunu yapmanın doğru yolu bir arayüze bağımlı olmak ve daha sonra bu arayüzün bir uygulamasını B Sınıfına enjekte etmektir.

Bir arayüz, güvenebileceğiniz en ince şeyle ilgilidir - Bir tutam duman yakalamaya çalışıyorum. Kod için çifte sahip bir şey ya da başka bir şey yapmayacağım, ancak bir arayüze bağlanması olarak alabilirsiniz ayrılmış, henüz arayüzler istediğiniz verebilecek tüm işlevsellik sağlamak gibi hakkındadır.

B Sınıfı'nın yapıcısının ihtiyaç duyduğu sınıfa bir arayüz almasını ve fabrikanın bu sınıfı arayüzün bir uygulayıcısı olarak üretmesini sağlayın. Fabrikaya bağlı değil, arayüze bağlı ve fabrikanın bu fabrikanın bir uygulamasını sağlamasını sağlayın.

Yani evet, bağımlılık enjeksiyonu kullanacaksınız, ancak bununla ilgili yanlış bir şey yok. Bağımlılık enjeksiyonu - özellikle basit yapıcı enjeksiyonu - bir şeyler yapmanın "normal" yolu olmalıdır. Uygulamanıza mainmümkün olduğunca geri gelen (ve ilk satırına yakın) yeni şeyler çıkarın ve yeni aramayı, şeyler oluşturmak için özel olarak tasarlanmış bir sınıfta gizleyin.

Alt satır: Bağımlılıkları enjekte etmekte tereddüt etmeyin. Bir şeyler yapmanın normal yolu bu olmalı.


Yapıcı enjeksiyonu yeni şeyleri mümkün olduğunca uzatıyor mu?
JeffO

Kötü oldu - Ben "mümkün olduğunca geri app" demek için sabit.
Nick Hodges

Evet. Bir fabrika yerine Parser arayüzüne bağlı olmayı düşünüyordum. Şimdi başka bir sınıf B sınıfı kullanıyorsa, B sınıfının bağlı olduğu arabirime bağlı olması gerekir. Bu, üst düzey sınıfa kadar devam edecektir. Bu üst düzey sınıfın nihayetinde Parser'ın uygun somut örneğini oluşturmak için bir fabrika kullanması gerekecektir. Üst düzey sınıf bir fabrikaya mı bağlı olmalı yoksa fabrikayı doğrudan kendi yöntemleri içinde mi kullanmalı?
CKing

1
İyi dedi: Bağımlılıkları enjekte etmekte tereddüt etmeyin
Signcodeindie

9

Sanırım öncülünüz burada biraz karışık, bir fabrikaya enjeksiyon yapmaktan bahsediyorsunuz, ancak fabrika deseni, DI çerçeveleri bu desen yaygın olmadığında, bir bağımlılık enjeksiyon çerçevesinin ne yaptığının bir alt kümesini yapmak olan yaratıcı bir modeldir. bu nedenle kullanışlıdır. Bununla birlikte, bir DI çerçeveniz varsa, DI çerçevesi fabrikanın yerine getireceği amacı yerine getirebileceğinden artık bir fabrikaya ihtiyacınız yoktur.

Bununla birlikte, bağımlılık enjeksiyonu ve genel olarak nasıl kullanacağınız hakkında biraz açıklayayım.

Bağımlılık enjeksiyonu yapmanın çeşitli yolları vardır, ancak en yaygın olanı yapıcı enjeksiyonu, özellik enjeksiyonu ve doğrudan DIContainer'dir. Özellik enjeksiyonu çoğu zaman yanlış yaklaşım (çoğu zaman doğru yaklaşım) olduğundan ve diğer yaklaşımlardan hiçbirini kesinlikle yapamayacağınız durumlar dışında DIContainer erişimi tercih edilmediğinden kurucu enjeksiyonu hakkında konuşacağım.

Yapıcı enjeksiyonu, bir bağımlılık için arabirime ve bu bağımlılık için somut uygulamayı bilen bir DIContainer'a (veya fabrikaya) sahip olduğunuz yerdir ve bu arayüze bağlı bir nesneye ihtiyaç duyduğunuz her yerde, inşaat sırasında uygulamayı fabrikadan teslim edersiniz. o.

yani

IDbConnectionProvider connProvider = DIContainer.Get<IDbConnectionProvider>();
IUserRepository userRepo = new UserRepository(connProvider);
User currentUser = userRepo.GetCurrentUser();

Birçok DI çerçevesi, bunu DIContainer'ınızın UserRepository yapıcısını somut uygulamaları bildiği arabirimler için inceleyeceği ve bunları sizin için otomatik olarak teslim edeceği yerde önemli ölçüde basitleştirebilir; Bu tekniğe sıklıkla İnversiyon Kontrol denir, ancak DI ve IoC'nin her ikisi de çok fazla değişime uğrayan ve belirsiz (varsa) farklılıklara sahip terimlerdir.

Şimdi, kapsayıcı kodun DIContainer'a nasıl eriştiğini merak ediyorsanız, ona erişmek için statik bir sınıfa sahip olabilirsiniz veya daha uygun olan şey, çoğu DI çerçevesinin bir DIContainer'ı yenileyebilmenize izin vermesidir; verilen arayüzler için somut olduğunu bildiği türler için dahili tekton sözlüğüne bir sarıcı.

Bu, kodda istediğiniz yerde DIContainer'ı yenileyebilir ve arayüz-somut ilişkilerinizi bilmek için önceden yapılandırdığınız DIContainer'ı etkili bir şekilde alabilirsiniz. DIContainer'ı doğrudan onunla etkileşime girmemesi gereken kod bölümlerinden gizlemenin olağan yolları, sadece gerekli projelerin DI çerçevesine referans olmasını sağlamaktır.


İlk paragrafa tam olarak katılmıyorum. Hala DI konteyneri tarafından enjekte edilen bir fabrikaya (uygulayıcı inteface) bağımlı olduğunuz senaryolar vardır.
Piotr Perak

Bence OP DI çerçeveleri veya DI kapları hakkında konuşmadı çünkü bu noktayı kaçırdın.
Doc Brown

@Jimmy Hoffa Çok ilginç noktalar yaparken, Bahar ve Bağımlılık Enjeksiyonu gibi IoC kaplarının farkındayım. Endişem, bir IoC çerçevesini kullanmadığınız bir senaryo ile ilgiliydi, bu durumda, sizin için bağımlılıklarınızı somutlaştıracak bir sınıf yazmanız gerekir. A sınıfı B arayüzüne bağlıysa ve C sınıfı A sınıfı kullanıyorsa, C sınıfı B arayüzüne bağlıdır. Birisi C Sınıfına B Sınıfı vermelidir. Meli C sınıfı sonra cla bağlıdır
cking

A sınıfı B arabirimine ve C sınıfı A sınıfını kullanıyorsa, C sınıfı B arabirimine bağlıdır. Birisi C Sınıfına bir B arabirimi vermelidir. C sınıfı daha sonra B arabirimine bağımlı mı yoksa örneği başlatan sınıfa mı bağlı olmalıdır? bağımlılıklar Yani fabrika. Bu soruya cevabınızı
vermişsiniz

benim gibi @bot, o Doc Brown belirtildiği gibi tüm senaryolarda doğru değil, ama göz benim kod örneği de ve değiştir Bir DI kabın işlevselliği bir alt kümesi olarak fabrikalar davranabilirsiniz büyük ölçüde, önsöz söyledi DIContainerile DbConnectionFactoryve kavram hala somut uygulamayı DI / Factory / etc nizden alıp inşaat süresinde bu tür tüketicilere teslim edeceğiniz anlamına gelir.
Jimmy Hoffa

5

Bir fabrikayı tıpkı başka bir şey geçirdiğiniz gibi bağımlılık enjeksiyonu yoluyla geçirebilirsiniz, durumun özyinelemesinin sizi karıştırmasına izin vermeyin. Uygulamak hakkında başka ne söyleyeceğimi bilmiyorum - bağımlılık enjeksiyonunu nasıl yapacağınızı zaten biliyorsunuz.

Fabrikaları düzenli olarak enjekte etmek için DI kullanıyorum.


1
Bir sınıf bir Fabrikaya bağlıysa, o sınıfı ünite test ederken fabrika ile dalga geçmeniz gerekir. Bunu nasıl yapıyorsun? Sınıf bir fabrika arayüzüne bağımlı olsun mu?
CKing

4

Fabrikaları enjekte etmede yanlış bir şey yok. 'Ana' nesnenin oluşturulması sırasında ne tür bir bağımlılığa ihtiyacınız olacağına karar veremiyorsanız standart bir yoldur. Bence örnek en iyi açıklayacaktır. Java bilmediğim için c # kullanacağım.


class Parent
{
    private IParserFactory parserFactory;
    public Parent(IParserFactory factory)
    {
        parserFactory = factory
    }

    public ParsedObject ParseFrom(string filename, FileType fileType)
    {
        var parser = parserFactory.CreateFor(fileType);
        return parser.Parse(filename);
    }
}
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.