Bu arasına Burada ayırt etmek önemlidir tek örnekleri ve Singleton tasarım deseni .
Tek örnekler basit bir gerçektir. Çoğu uygulama, bir seferde yalnızca bir yapılandırma, bir seferde bir kullanıcı arayüzü, bir seferde bir dosya sistemi vb. İle çalışmak üzere tasarlanmıştır. Korunacak çok fazla durum ya da veri varsa, o zaman kesinlikle sadece bir örneğe sahip olmak ve mümkün olduğunca uzun süre hayatta kalmasını istersiniz.
Singleton tasarım deseni çok özel bir tek örnek türüdür , özellikle aşağıdakilerden biridir:
- Genel, statik örnek alanı aracılığıyla erişilebilir;
- Program başlangıcında veya ilk erişime girildiğinde;
- Hiçbir kamu kurucusu (doğrudan somutlanamaz);
- Asla açıkça serbest bırakılmamalıdır (programın sona ermesinde dolaylı olarak serbest bırakılmıştır).
Bu özel tasarım seçiminden dolayı, desenin birkaç potansiyel uzun vadeli problemi ortaya çıkarmasından kaynaklanmaktadır:
- Özet veya arayüz sınıfları kullanamama;
- Alt sınıflamanın yetersizliği;
- Uygulama boyunca yüksek bağlantı (değiştirilmesi zor);
- Test etmek zor (birim testlerde sahte / alay edilemez);
- Değişken hal durumunda paralelleştirmek zor (kapsamlı kilitleme gerektirir);
- ve bunun gibi.
Bu belirtilerden hiçbiri aslında tek örneklere endemik değildir, sadece Singleton paterni.
Bunun yerine ne yapabilirsiniz? Singleton desenini kullanmayın.
Sorudan alıntı:
Fikir, verileri depolanan ve senkronize eden uygulamada bir yere sahip olmaktı ve ardından açılan yeni ekranlar, sunucudan gelen çeşitli destekleyici veriler için tekrarlanan taleplerde bulunmaksızın, ihtiyaç duydukları şeyin çoğunu sorgulayabilir. Sunucuya sürekli istekte bulunmak çok fazla bant genişliği alırdı - ve haftada binlerce dolar fazladan İnternet faturasından söz ediyorum, bu kabul edilemezdi.
Bu kavramın, bir nevi ipucu olarak, ancak belirsiz olduğu bir adı vardır. Buna önbellek denir . Fantezi edinmek istiyorsanız, buna "çevrimdışı önbellek" veya yalnızca uzaktaki verilerin çevrimdışı bir kopyası diyebilirsiniz.
Bir önbellek bir singleton olması gerekmez. Bu olabilir Birden önbellek örnekleri için aynı veriler alınırken kaçınmak istiyorsanız tek örneği olması gerekir; ama bu aslında her şeyi herkese açık tutmanız gerektiği anlamına gelmez .
Yapacağım ilk şey , önbelleğin farklı işlevsel alanlarını ayrı arayüzlere ayırmak. Örneğin, Microsoft Access'i temel alarak dünyanın en kötü YouTube klonunu yaptığınızı varsayalım:
MSAccessCache
▲
|
+ ----------------- + ----------------- +
| | |
IMediaCache IProfileCache IPageCache
| | |
| | |
VideoPage MyAccountPage MostPopularPage
Burada , belirli bir sınıfın erişmesi gerekebilecek belirli veri türlerini tanımlayan birçok arayüze sahipsiniz - medya, kullanıcı profilleri ve statik sayfalar (ön sayfa gibi). Bunların hepsi bir mega önbellek tarafından gerçekleştirilir , ancak bireysel sınıflarınızı bunun yerine arayüzleri kabul edecek şekilde tasarlarsınız, böylece ne tür bir örnek aldıklarını umursamazlar. Fiziksel örneği, programınız başladığında bir kez başlatırsınız ve ardından, örnekleri (belirli bir arabirim türüne gönderir) yapıcılar ve genel özellikler aracılığıyla aktarmaya başlarsınız.
Bu arada, Bağımlılık Enjeksiyonu olarak adlandırılır ; Spring veya herhangi bir özel IoC kabını kullanmanıza gerek yok; genel sınıf tasarımınız bağımlılıklarını kendi başına başlatmak veya global durumuna atıfta bulunmak yerine arayandan kabul ettiği sürece .
Arayüz tabanlı tasarımı neden kullanmalısınız? Üç sebep:
Kodun okunmasını kolaylaştırır; Bağımlı sınıfların tam olarak hangi verilere bağlı olduğunu arabirimlerden net bir şekilde anlayabilirsiniz .
Microsoft Access'in bir veri arka ucu için en iyi seçenek olmadığını fark ederseniz, bunu daha iyi bir şeyle değiştirebilirsiniz - SQL Server diyelim.
SQL Server'ın özellikle medya için en iyi seçenek olmadığını fark ederseniz, uygulamanızı sistemin başka bir bölümünü etkilemeden kesebilirsiniz . Bu, soyutlamanın gerçek gücünün girdiği yerdir.
Bir adım daha ileri gitmek istiyorsanız, Spring (Java) veya Unity (.NET) gibi bir IoC kabı (DI framework) kullanabilirsiniz. Neredeyse her DI çerçevesi kendi yaşam boyu yönetimini yapacak ve belirli bir hizmeti tek bir örnek olarak tanımlamanıza izin verecektir (genellikle "singleton" olarak adlandırılır, ancak bu yalnızca tanıdıklık içindir). Temel olarak bu çerçeveler, örneklerin etrafından elle geçerek yapılan maymun çalışmasının çoğunu kurtarır, ancak kesinlikle gerekli değildir. Bu tasarımı uygulamak için herhangi bir özel araca ihtiyacınız yoktur.
Tamlık uğruna, yukarıdaki tasarımın gerçekten de ideal olmadığını belirtmeliyim. Önbellekle uğraşırken (olduğu gibi), aslında tamamen ayrı bir katmana sahip olmanız gerekir . Başka bir deyişle, bunun gibi bir tasarım:
+ - IMediaRepository
|
Önbellek (Genel) --------------- + - IProfilRepository
▲ |
| + - IPageRepository
+ ----------------- + ----------------- +
| | |
IMediaCache IProfileCache IPageCache
| | |
| | |
VideoPage MyAccountPage MostPopularPage
Bunun yararı, Cache
yeniden ateşlemeye karar verirseniz , örneğinizi asla kesmenize gerek kalmamasıdır; Medya'nın saklanma şeklini, alternatif bir uygulamasını besleyerek değiştirebilirsiniz IMediaRepository
. Bunun nasıl bir araya geldiğini düşünürseniz, bunun yalnızca bir fiziksel önbellek örneği oluşturduğunu göreceksiniz, bu yüzden asla aynı verileri iki kez almak zorunda kalmayacaksınız.
Bunların hiçbiri, dünyadaki her bir yazılım parçasının, bu yüksek uyum ve gevşek bağlantı standartlarına uyması gerektiğini söylemek değildir; Bu, projenin boyutuna ve kapsamına, ekibinize, bütçenize, son teslim tarihlerine vb. bağlıdır.
Not: Diğerlerinin de belirttiği gibi, bağımlı sınıfların bir önbellek kullandıklarının farkında olmaları muhtemelen en iyi fikir değildir - bu, kesinlikle umursamayacakları bir uygulama detayıdır. Olduğu söyleniyor, genel mimari hala yukarıda gösterilene çok benzeyecek, bireysel arayüzlere önbellek olarak bakmayacaktınız . Bunun yerine, onlara Hizmetler veya benzeri bir ad verin .