Effective Java Item 1: Static Factory Methods [TR]
"Effective Java", dil hakkında belirli bir seviyeye geldikten sonra Java'nın ince detaylarını ve best-practice lerini kapmamız için faydalı bir kaynaktır. Kitapta bahsedilen ilk konu static factory metotlarıyla alakalıdır. (peşinen not: factory pattern ile ilgili bir durum değildir.)
Biliyoruz ki OOP'de obje oluşturmak için yapıcı(constructor) metotları kullanırız. Bu yapıcı metotlarımız sınıfın ismi ile aynı, bir return ettiği değer olmayan, çeşitli kısıtlar ile tanımladığımız -instantiation- araçlardır. Yani objeyi yaratır, ilk değer atamalarını burada yaparız. Fakat bu nesne oluşturmanın tek ve yegane yolu değildir. Bir diğer yol ise bu makalenin konusu ve kitabın ilk maddesi olan Static Factory Metot lardır.
İlk olarak bir Pokemon class'ımız olduğunu düşünelim ve yeni bir pokemon nesnesi yaratmak için name ve level bilgisine ihtiyaç duyduğumuzu varsayalım. Constructor'ı aşağıdaki gibi olacaktır. Class ismiyle aynı, herhangi bir geri dönüş tipi yok. Parametreleri alıp objenin attribute'larını tanımlıyor, kısaca pokemonu yaratıyoruz.
private Pokemon(String name, int level) {
this.name= name;
this.level= level;
}
Şimdi bu hikayeye bir de static factory method ekleyerek göz atalım. Constructor'ımız mevcut iken yeni bir statik metot oluşturuyoruz, bu metoda canımız ne isim istiyorsa onu veriyoruz. Dolayısıyla bir avantaja burada sahip oluyoruz. Yapıcı fonksiyonları özel bir isimle tanımlayamazken, static factory metotlar bize daha tanımlayıcı isimlerle obje oluşturma fırsatı sunar.
private Pokemon(String name, int level) {
this.name= name;
this.level= level;
}
public static Pokemon createNewPokemon(String name, int level) {
return new Product(name, level);
}
Bir diğer sağladığı avantaj ise kaynak optimizasyonudur, biz yapıcı metotları her çağırdığımızda yepyeni bir obje oluşur. Fakat biz tek bir obje oluşturup işlemlerimizi onun üzerinden yürütmek istiyorsak static factory metotlar imdadımıza burada da yetişir. Belki son 2-3 cümle size Singleton Pattern'i anımsatmıştır.
private static SingletonObject myInstance;
private SingletonObject (){}
public static SingletonObject getInstance(){
if (myInstance== null){
myInstance= new SingletonObject ();
}
return myInstance;
}
Yukarıdaki sınıfta getInstance adında bir statik factory metot tanımladık. Şimdi bu statik metotu kullanarak bir obje yaratmaya çalışalım.
SingletonObject mySingletonObject = SingletonObject.getInstance();
İlk defa obje yaratmak için statik metodu doğrudan sınıf üzerinden çağırırız, daha öncesinde myInstance objesi oluşturulmadığı için if içerisine girer new ile yeni objeyi yaratır, myInstance propertysinin içerisine atarız. Bu pattern sayesinde statik metod bizim yeni bir nesne üretmemizi engeller. Biz SingletonObject sınıfından getInstance metotunu artık her çağırdığımızda, en başta oluşturduğumuz o tek objeyi verecektir. Bu pattern database bağlantısını yönetmede, logging gibi durumlarda sıkça kullanılır.
Başka bir avantaj ise daha sub-class türlerinde objeleri return edebilme esnekliğidir. Örneğin ilk örnekte pokemon class'ından bahsetmiştik. Pokemon oluşturmak istiyoruz fakat verdiğimiz koşula bağlı olarak Elektrik veya çim pokemonu oluşturacağız. Tek bir statik factory metot ile koşula bağlı olarak return ettiğimiz class tipi değişecek(Fakat özünde yine bir Pokemon return etmiş olacağız).
public final class PokemonFactory {
public static Pokemon getPokemon(boolean condition) {
if(condition) {
return new electricPokemon();
}
else {
return new grassPokemon();
}
}
}
Bunun haricinde constructor içindeki kod kalabalığını azaltmak, single-responsibility'i bozmamak için de kullanılırlar. Örneğin her obje oluştuğunda x,y,z olayları da olsun.(log, ıvır zıvır) Bu rastgele x,y,z olaylarının her birini constructor içerisine kodlamak, single-responsibility'i bozup, gereğinden fazla uzun ve kalabalık bir yapıcı metot oluşturmamıza sebep olur. Bu gibi özel durumları çözmek için de static factory metotları kullanabiliriz.
Diğer kısımları da umarım vakit bulursam anlatmaya çalışacağım, okuduğunuz için teşekkür ederim, yorum yazarsanız konu hakkında tartışabiliriz.
Github
LinkedIn
Email