Normal şekilde, sınıfı kullanan kişi, o sınıftan bir örnek oluşturabilme iznini public(herkese açık) yapılandırıcı sayesinde elde eder. Her programcının bilmesi gereken başka bir teknik daha vardır. Bir sınıf, kendi örneğini döndüren statik fabrika metodu ile de örneğini oluşturabilir. Boolean(basit boolean tipinin kutulanmış sınıf hali) sınıfından basit bir örnek.
Effective Java - Madde 1: Yapılandırıcılar yerine statik fabrika(factory) metotlarını kullan
1. EFFECTIVE JAVA – Madde 1
JOSHUA BLOCH
BY İBRAHİM KÜRCE, @IBRAHIMKURCE
2. BÖLÜM 2 : NESNELERİ OLUŞTURMA VE
YOKETME
Bu bölüm nesneleri oluşturma ve yok etme ile ilgilidir. Bu bölümde, nesneler ne zaman ve nasıl
oluşturulur, ne zaman ve nasıl oluşturulmaması gerekir, zaman kısıtlı durumlarda yok edilmesi
nasıl sağlanır ve yok edilmeden önce nesnelere ait temizleme işlemleri nasıl yönetilir gibi
sorulara cevap aranır.
3. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
Normal şekilde, sınıfı kullanan kişi, o sınıftan bir örnek oluşturabilme iznini public(herkese açık)
yapılandırıcı sayesinde elde eder. Her programcının bilmesi gereken başka bir teknik daha vardır.
Bir sınıf, kendi örneğini döndüren statik fabrika metodu ile de örneğini oluşturabilir.
Boolean(basit boolean tipinin kutulanmış sınıf hali) sınıfından basit bir örnek. Bu metot boolean
değerini, Boolean nesne referansına dönüştürür:
Not: Statik fabrika metodu Fabrika Metot Modeli(Pattern) ile aynı şey değildir.
Bir sınıf, onun kullanıcılarına public yapılandırıcılar yerine statik fabrika metotları sunabilir. Statik
fabrika metodu sunmanın birçok fayda ve zararı vardır.
4. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
Statik fabrika metotlarının bir faydası, public yapılandırıcı aksine, isimlerinin olmasıdır.
Yapılandırıcının parametreleri dönen nesneyi iyi tarif etmemesine rağmen, güzel bir isimle
seçilmiş statik fabrika metodu kullanılması ve okunması kolay bir kod ortaya çıkarır. Örneğin,
BigInteger(int, int, Random) yapılandırıcı büyük ihtimalle asal olan BigInteger nesnesi döner. Eğer
BigInteger.probablePrime(Bu metot Java 1.4 sürümünde eklenmiştir) statik metodu olarak
adlandırılsaydı daha iyi ifade edilmiş olurdu.
Aynı imza ile bir sınıfın tek bir yapılandırıcısı olabilir. Programcılar bu kısıtı, parametre tipleri
farklı olan parametre listeleri tanımlayarak birden fazla yapılandırıcı oluşturabiliyordu. Bu kötü
bir fikirdi. Böyle bir kütüphaneyi(API) kullanan kullanıcılar, hangi yapılandırıcının ne işe yaradığını
hiçbir zaman hatırlayamazlar ve yanlış parametre ile yapılandırıcı çağırmaktan kurtulamazlar. Bu
kodu okuyan insanlar, kodun dökümanına bakmadan, bu yapılandırıcıların ne iş yaptıklarını
bilemezler.
5. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
Statik fabrika metotlarının isimleri oldukları için önceki parağrafta yapılandırıcılar için bahsedilen
kısıtlamaları paylaşmazlar. Çoklu yapılandırıcı kullanılması gereken durumlarda, yapılandırıcılar
yerine statik fabrika metotları kullanın ve bu metotların farklılıklarını anlaşılır kılan isimler seçin.
Statik fabrika metotlarının ikinci faydası, yapılandırıcıların aksine, çağrıldıkları her seferinde
yeni bir nesne oluşturmak zorunda değildirler. Bu fayda, değişmez sınıflara(Madde 15)
önceden-yapılandırılmış örnekler yada önbelleğe(cache) alınmış örnekler oluşturulmasını ve
gereksiz olarak birçok nesne oluşturulmasının önüne geçilmesini sağlar.
Boolean.valueOf(boolean) metodu bu tekniğe örnektir: metot hiçbir zaman nesne oluşturmaz.
Bu teknik Flyweight(Sineksiklet) modeline benzer. Bu oluşturulması maliyetli olan ve sıkça ihtiyaç
duyulan nesneler için büyük performans artışı sağlar.
Statik fabrika metotlarının tekrarlı çağırılsalar bile dönen aynı nesnelerini kontrol edebilme
özelliği, herhangi bir anda, ne tür örneklere sahip olduğu bilgisi hakkında sıkı bir kontrol hakkı
verir. Bunu yapan sınıflara kontrollü-örneklendirilmiş(instance-controlled) sınıflar denir. Böyle
sınıflar yazmanın birçok sebebi olabilir.
6. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
Örneği kontrol etmek, sınıfa tekiz(singleton) veya örneklenememe(noninstantiable) özelliklerini
garanti eder(Madde 3 ve 4). Ayrıca iki örneği eşit olmayan, değişmez sınıflara(immutable, sadece
a==b doğru olursa, a.equals(b) doğru olan sınıflar) izin verir(Madde 15). Bir sınıf bu eşitliği
garantilerse, equals(Object) metodu yerine == operatörü kullanılabilir, bu da performans artışı
sağlar. Enum tipleri bunu garanti eder.
Statik fabrika metotlarının üçüncü faydası, yapılandırıcıların aksine, dönüş yaptığı tiplerin alt-
tiplerini de dönebilmesidir. Bu dönen nesnenin tipini seçmede büyük bir esneklik sağlar.
Bu esnekliğin bir uygulaması; kullanılan kütüphanede dönen nesnelerin sınıflarını public yapma
gereği duymaz. Kütüphanedeki kullanılan sınıfları gizlemek, kütüphaneyi etkili ve güçlü kılar. Bu
teknik arayüz-tabanlı(interface-based) çatılar(frameworks) yazmamıza olanak sağlar. Arayüz
statik fabrika metotları için doğal dönüş tipleri sağlar. Arayüzler statik metotlara sahip olamazlar,
bu yüzden Type adlı bir arayüz için oluşturulan statik fabrika metotları, Types adlı
örneklenemeyen bir sınıfa konur.
7. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
Örneğin, Java Collections çatısı koleksiyon arayüzleri için 32 adet kullanıma hazır, gerçeklenmiş sınıfı
vardır. Bunların bazıları değiştirilemez koleksiyonlar, bazıları da senkronize edilmiş koleksiyonlardır,
daha birçoğu vardır. Bütün bu gerçeklenmiş sınıflar, statik fabrika metotları ile kullanılabilir ve
örneklenebilir değillerdir(new anahtar sözcüğü ile yeni nesneleri oluşturulamaz). Dönen nesnelerin
sınıflarının hepsi public olmayan sınıflardır.
Collections Çatı kütüphanesi sahip olduğu dışarı açık olan 32 public sınıftan, ki her biri kullanıma açık
gerçeklenmiş halidir, daha küçük. Sadece yığınsal olarak kütüphanenin küçüklüğü değil, kavramsal
hafiflik olarak küçüklük. Kullanıcı biliyor ki, arayüz tarafından döndürülen nesne tam olarak
kütüphanede belirtilen nesnedir, bu yüzden gerçeklenmiş sınıflar için ayrıca döküman okumaya gerek
yok. Ayrıca, statik fabrika metotları kullanmak, kullanıcıya dönüş tipi olarak arayüz dönmeyi tavsiye
eder, arayüzü gerçeklemiş sınıflar değil.
Public statik fabrika metodu tarafından dönülen nesnenin public olmaması yetmez, ayrıca static
fabrikaya geçilen parametre değerlerine göre dönüş tipi değişebilir. Dönüş tipinin alt-tiplerini de
metot dönebilir. Dönüş tipi, yazılımdaki bakım ve performans artışına göre uygulamanın değişiklik
versiyonlarında farklılık gösterebilir.
8. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
java.util.EnumSet sınıfının, 1.5 sürümünde eklendi, public yapılandırıcıları yoktur, sadece statik fabrika
metotları vardır. Altındaki enum tipinin boyutuna göre iki sınıftan birini dönebilir: 64 veya daha az
elemanı varsa, çoğu enum gibi, fabrika metodu RegularEnumSet örneğini döner, ki bu sınıf arka
planda tek long tutar. 65 veya daha fazla olursa, fabrika metodu JumboEnumSet örneği döner, arka
planda long dizisi tutar.
Bu iki gerçeklenmiş sınıflar kullanıcıya görünmezdir. Eğer RegularEnumSet küçük enum tiplerinde
performans artışı sağlamazsa, gelecek sürümlerde herhangi bir sorun olmadan kütüphaneden
çıkarılabilir. Benzer şekilde performans artışı sağlanacağı düşünülürse, gelecek sürümlerde 3. veya 4.
EnumSet sınıfının gerçeklenmiş hali eklenebilir. Kullanıcılar fabrika metotundan dönen nesnenin
tipiyle ilgilenmezler, sadece dönen tip EnumSet olması onlar için yeterlidir.
Statik fabrika metotundan dönen nesnenin sınıfı, metotun yazıldığı dönemde var olmayabilir. Böyle bir
esnek fabrika metodu, servis sağlayan(service provider) çatıların temelini oluşturur. Java Database
Connectivity API (JDBC) buna bir örnektir. Servis sağlayan çatılar, içinde servisleri gerçekleyen birçok
servis sağlayıcıyı barındıran bir sistemdir. Bu sistem, kullanıcıları için hazır gerçeklenmiş sınıflar sunar
ve onları gerçeklemelerden ayrıştırır.
9. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
Servis sağlayan çatıların 3 gerekli bileşeni vardır: servis arayüzü, ki sağlayıcılar bunları gerçekleyecek;
sağlayıcının kayıt olacağı kütüphane, ki sistem bunu kullanarak kullanıcılarına kütüphaneye erişim
hakkı verecek; servis erişim kütüphanesi, ki kullanıcılar bunun sayesinde servisin örneğini elde
edebilecekler. Servis erişim kütüphanesi kullanıcıları için sağlayıcı seçmesinde bazı kriterler
belirtmesini isteyebilir ama zorunlu değil. Bu belirlemeler olmazsa kütüphane varsayılan gerçeklemeyi
döner. Servis erişim kütüphanesi esnek bir statik fabrikadır ve servis sağlayan çatının temelini
oluşturur.
Servis sağlayan çatılarının isteğe bağlı 4.bileşeni olabilir, bu servis sağlayan arayüzdür. Bu arayüz servis
gerçeklemesinin nesnesini oluşturmak için gerekli arayüzü sağlar. Servis sağlayan arayüz yokluğunda,
gerçekleyen sınıf adı üzerinden kayıt olur ve örneği reflection yöntemi ile oluşturulur(Madde 53).
JDBC kütüphanesinde, Connection sınıfı servis arayüzü rolünde oynar, DriverManager.registerDriver
metodu sağlayacının kayıt olacağı kütüphane, DriverManager.getConnection metodu servis erişim
kütüphanesi ve Driver sınıfı servis sağlayan arayüzü oluşturur.
Birçok servis sağlayan çatı modeli vardır. Örneğin, servis erişim kütüphanesi gerekli görülen
sağlayıcıdan daha zengin bir servis arayüzü dönebilir. Adapter modelini kullanarak yapar bunu. Servis
sağlayıcı arayüzü ve varsayılan sağlayıcının basit bir gerçekleme örneği:
11. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
Statik fabrika metotlarının 4.faydası parametreli tip örneği oluşturulmasındaki ayrıntıları
azaltmasıdır. Maalesef, kapsamından belli olmasına ragmen, parametreli bir yapılandırıcı
çağırırsan, tip parametrelerini belirtmen gerekiyor. Bu da tip parametresini 2 kere belirtmene
neden oluyor:
Bu gereksiz belirtim zamanla parametre sayısındaki artışla beraber boyut ve karmaşıklıkta artışa
neden olur. Statik fabrika ile derleyici parametre tipleri anlayabilir. Buna tip çıkarımı(type
inference) denir. Örneğin;
Not: Java 7 ile tip çıkarımı eklenmiştir. İ.K.
12. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
Sonra az önceki karmaşık ifadeyi daha özlü bir ifade ile değiştirebilirsiniz:
Birgün Java dili bu tür tip çıkarımlarını yapılandırıcı çağrıları üzerinden gerçekleyebilir ama 1.6
sürümüne kadar bu mümkün değildir.
Maalesef, standart koleksiyon gerçeklemeleri, HashMap gibi, statik fabrika metotları 1.6
sürümüne kadar yoktur ama yararlı metotların tanımlandığı sınıfa kendiniz ekleyebilirsiniz. Daha
önemlisi, kendi parametreli sınıfınızda bile kullanabilirsiniz.
Sadece statik fabrika metotları sağlamanın başlıca zararı, public yada protected(korumalı)
yapılandırıcı olmayan sınıflardan alt-sınıflar türetilemez. Aynısı public statik fabrika tarafından
dönülen public olmayan sınıflar için de geçerlidir. Örneğin; Collections çatısındaki gerçeklenen
sınıfların alt-sınıflarını oluşturmak münkün değildir. Bu bazı durumlarda iyi birşey olabilir,
programcıyı kalıtım kullanmak yerine kompozisyon(composition) kullanımına teşvik eder(Madde
16).
13. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
Statik fabrika metotlarının ikinci zararı ise diğer statik metotlardan kolayca ayırt
edilememesidir. Statik metotlar, yapılandırıcılar gibi göze çarpmazlar, o yüzden yapılandırıcıların
aksine statik fabrika metotlar ile sınıfın örneğinin nasıl oluşturulacağını anlamak zor olabilir.
Javadoc belki birgün bu konuda dikkatleri statik fabrika metotlarının üzerine çekebilir. Bu arada,
sınıf veya arayüz içerisine gerekli yorumlar yazarak ve ortak isimlendirme geleneklerine bağlı
kalarak bu zararı en aza indirebilirsiniz. Bazı statik fabrika metot ortak isimleri:
• valueOf— Parametre geçilen değer ile aynı değere sahip örneği döner. Böyle statik fabrikalar
tip çevrim metotlarıdır.
• of— valueOf un kısa alternatifidir, EnumSet tarafından kullanılır.
• getInstance— Parametreler tarafından belirtilen örneği döner ama aynı değer sahip olduğu
söylenemez. Tekiz(singleton) sınıflarda, hiçbir parametre almaz ve tek örneği döner.
• newInstance— getInstance gibi ama her seferinde farklı bir örnek döner.
14. Madde 1: Yapılandırıcılar yerine statik fabrika(factory)
metotlarını kullan
• getType— getInstance gibi ama fabrika metodu başka bir sınıftayken kullanılır. Type, dönüş
yapmasını istediğimiz nesnenin tipidir.
• newType— getType ile aynı.
Özet olarak, statik fabrika metotları ve public yapılandırıcıların kendi kullanım alanları vardır ve
bu alanları anlamalıyız. Genelde statik fabrika metotları tercih edilebilir.