Neden statik yöntemler yerine tekli kullanılıyor?


94

Yardımcı / yardımcı sınıflar hakkındaki bu basit sorulara hiçbir zaman iyi cevaplar bulamadım:

Neden statik yöntemler kullanmak yerine tekli (durumsuz) oluşturayım?

Bir nesnenin durumu yoksa neden bir nesne örneğine ihtiyaç duyulur?



2 farklı dilde konuştuğumuz için düşünmeyin, bu yüzden cevap değişebilir, ancak bağlantı için teşekkürler, java'da "monostate" terimini hiç duymamış
Sebastien Lorber

Yanıtlar:


79

Genellikle, bir uygulamaya bir tür küresel durumu tanıtmak için tek tonlar kullanılır . (Dürüst olmak gerekirse, gerçekten gerekenden daha sık, ama bu başka bir zaman için bir konu.)

Ancak, devletsiz bir bekarın bile yararlı olabileceği birkaç köşe durumu vardır :

  • Öngörülebilir gelecekte bunu devletle genişletmeyi bekliyorsunuz.
  • Belirli bir teknik neden için bir nesne örneğine ihtiyacınız var . Örnek: C # veya Java ifadesi için senkronizasyon nesneleri .
    locksynchronized
  • Kalıtıma ihtiyacınız var, yani aynı arayüzü kullanarak ancak farklı bir uygulama kullanarak singleton'unuzu başka biriyle kolayca değiştirebilmek istiyorsunuz.
    Örnek: Toolkit.getDefaultToolkit()Java'daki yöntem, tam türü sisteme bağlı olan bir tekli döndürür.
  • Sentinel değer için referans eşitliği istiyorsunuz . Örnek: C # içinde.
    DBNull.Value

27
IMHO singletonları küresel durumları tanıtmak için kötüye kullanılsa da +1 ile gideceğim . Bir tekil yapmanın amacı, bir nesneyi küresel olarak kullanılabilir kılmak değil, bir nesnenin yalnızca bir kez örneklenmesini sağlamaktır. Küresel nesneler gerekli bir kötülüktür. Gerçekten gerekli olmadıkça, bunları kullanmamaya çalışılmalıdır, çünkü bunlar genellikle her yerde SomeSingleton.getInstance (). SomeMethod () ile yüksek eşleşmeye yol açar. :)
back2dos

Birden fazla işleme örneği yerine yalnızca bir işleme örneği istediğiniz oyunlarda veya bir seferde yalnızca bir bağlantı olabilen güvenli bir kanal kurduğunuz bir ağ borulama sınıfında yararlı olabilir.
Tschallacka

2
"Tekliğinizi kolayca değiştirin" kısmı benim bakış açımdan en önemli nokta. Rest, statik sınıf uygulamasına oldukça yakındır.
Teoman shipahi

1
Singletons, toplam / ürün türleri ve benzerleri için yararlı Boş olmayan sentinel değerlerdir. Örneğin, bir Seçenek türündeki Hiçbiri / Hiçbir Şey değeri veya bir koleksiyon türü için Boş değer olmak. Bonus olarak hızlı bir şekilde Yok / Boş testi alırsınız, çünkü gereken tek şey referans eşitliğidir.
itsbruce

@itsbruce: Örnekleriniz tekil değil : Boş liste, List sınıfının tek olası örneği değildir ve None değeri Option sınıfının tek olası örneği değildir. Ancak, orada nöbetçi değer örnektir olan singletonların ve benim cevaba tane eklemek için özgürlük almış. Giriş için teşekkürler!
Heinzi

37

Statik yöntemler sınıfı, yani Bağımlılık Enjeksiyonu yerine durumsuz bir singleton kullanıldığını görebiliyordum .

Doğrudan kullandığınız yardımcı bir yardımcı sınıf işlevlerine sahipseniz, bu gizli bir bağımlılık oluşturur; onu kimin veya nerede kullanabileceği konusunda hiçbir kontrole sahip değilsiniz. Aynı yardımcı sınıfın durum bilgisi olmayan bir tekil örnek aracılığıyla enjekte edilmesi, nerede ve nasıl kullanıldığını kontrol etmenize ve gerektiğinde değiştirmenize / alay etmenize / vb. Olanak tanır.

Bunu tekil örnek yapmak basitçe, gerekli olandan daha fazla türde nesneyi ayırmamanızı sağlar (çünkü yalnızca bir tanesine ihtiyacınız vardır).


1
"Kimin, nerede kullanabileceği konusunda hiçbir kontrolünüz yok." Neden birisi buna ihtiyaç duysun?
hagrawal

1
@hagrawal, test amacıyla alay edebilmelisiniz
Jemshit Iskenderov

15

Aslında burada belirtilmeyen başka bir cevap buldum: statik yöntemlerin test edilmesi daha zordur.

Çoğu test çerçevesi, örnek yöntemlerle alay etmek için harika çalışıyor, ancak çoğu statik yöntemlerin taklidini düzgün bir şekilde ele almıyor.


2
Ancak Powermock bunu başarabilecek gibi görünüyor
Sebastien Lorber

6

Çoğu programlama dilinde sınıflar pek çok tip sistemi atlatır. Statik yöntemleri ve değişkenleriyle bir sınıf bir nesne olsa da, çoğu zaman bir arabirim uygulayamaz veya diğer sınıfları genişletemez. Bu nedenle, başka bir türün alt tipi olamayacağı için polimorfik bir şekilde kullanılamaz. Bir arabirim varsa, örneğin, IFooablediğer sınıfları birçok yöntem imzalarla gereklidir, sınıf nesnesi StaticFooyerine kullanılamaz IFooableise, FooSingleton.getInstance()kutu (varsayılarak FooSingletonuygular IFooable).

Lütfen unutmayın, Heinzi'nin cevabına yorum yaptığım gibi, bir tekil, somutlaştırmayı kontrol etmek için bir modeldir. Yazarına veren new Class()ile değiştirilirClass.getInstance()Class , gereksiz örneklerin oluşturulmasını önlemek için kullanabileceği örnekler üzerinde daha fazla kontrol . Tekli, fabrika modelinin çok özel bir durumudur ve bu şekilde ele alınmalıdır. Yaygın kullanım, bunu daha ziyade küresel kayıtların özel bir durumu haline getirir, bu da genellikle kötü sonuçlanır, çünkü küresel kayıtlar sadece isteyerek kullanılmamalıdır.

Genel yardımcı işlevler sağlamayı planlıyorsanız, statik yöntemler iyi çalışacaktır. Sınıf, sınıf olarak değil, sadece bir ad alanı olarak hareket edecektir. Size yüksek uyumu korumanızı öneririm, yoksa en tuhaf çiftleşme sorunları yaşayabilirsiniz.

greetz
back2dos


4

Hangisini kullanmak arasında bir değiş tokuş var. Tekillerin durumu olabilir veya olmayabilir ve nesnelere atıfta bulunurlar. Durumu korumuyorlarsa ve yalnızca genel erişim için kullanılıyorlarsa, bu yöntemler daha hızlı olacağından statik daha iyidir. Ancak nesneleri ve OOP kavramlarını (Kalıtım polimorfizmi) kullanmak istiyorsanız, o zaman singleton daha iyidir.

Bir örnek düşünün: java.lang.Runtime, java'da bir singleton sınıfıdır. Bu sınıf, her JVM için farklı uygulamalara izin verir. Uygulama, JVM başına tekdir. Bu sınıf statik olsaydı, JVM'ye dayalı farklı uygulamaları geçemeyiz.

Bu bağlantıyı gerçekten yararlı buldum: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html ?

Umarım yardımcı olur!!


Bu cevap, gerçek dünyaya somut bir örnek eklemek için iyidir.
Geoffrey

2

Benim için "Nesne Durumunun Singleton kullanmasını istiyorum, İstenen Fonksiyonun statik yöntemi kullanmasını istiyorum"

Ne istediğine bağlı. Nesne durumunu istediğinizde (örneğin null, yerine Null durumu gibi Polimorfizm veya varsayılan durum), tekli sizin için uygun seçimdir, oysa statik yöntem işleve ihtiyaç duyduğunuzda kullanılır (Girişleri al ve sonra bir çıktı döndür).

Tekil durum için tavsiye ederim, somutlaştırıldıktan sonra her zaman aynı durumda olmalıdır. Klonlanabilir olmamalı ve ayarlanacak herhangi bir değer almamalıdır (dosyadan statik yapılandırma hariç, örneğin java'daki özellikler dosyası).

Not: Bu ikisi arasındaki performans milisaniye cinsinden farklıdır, bu nedenle önce Mimariye odaklanın .


1

Singleton vatansız değil, küresel durumu elinde tutuyor.

Singleton kullanmayı düşünebileceğim bazı nedenler:

  • Bellek sızıntılarını önlemek için
  • Bir uygulamadaki tüm modüller için aynı durumu sağlamak için, örneğin veritabanı bağlantısı

Biliyorum ama aslında bir singleton aşağı yukarı devletsiz olabilir ... Herhangi bir sınıf özelliğini paylaşmıyorsa ...
Sebastien Lorber
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.