İçeriğe geç

Factory Tasarım Kalıbı

Merhaba arkadaşlar,

Bu yazıda “Factory Design Pattern” i anlatmaya çalışacağım.

“Factory” nin kelime anlamı “fabrika” demektir. Fabrika deyince aklımıza ne geliyor? Üretim. O zaman bu patternimiz de demekki creational tasarım kalıpları arasında.

Peki üretir ama ne üretecek? Aklımıza gelebilecek her şeyi, yani bizim için bunlar nesne oluyor,  her nesneyi üretebilir.

Nesneyi oluşturma görevini müşteriden, fabrikaya bırakmak için bu kalıp kullanılır.

Örneğin kullandığımız telefonu, bayiler değil de fabrika üretir değil mi? Biz de üretme, yani nesneyi oluşturma, yani kaba tabir ile “nesneyi new leme” işlemini bayilere değil fabrikalara vereceğiz.

Telefon örneğinden gidersek, Samsung telefon fabrikasını modelleyelim. Fabrika bizlere s8 ve note8 modellerini üretiyor olsun.

Öncelikle s8 ve note8 i soyutlayacağımız bir arayüz oluşturmalıyız.

public interface Telefon {

    String getModel();
    String getBatarya();
    int getEn();
    int getBoy();
}

Sonrasında bu class ların implementasyonu olan s8 sınıfını oluşturalım.

public class S8 implements Telefon {

    private String model;
    private String batarya;
    private int en;
    private int boy;

    @Override
    public String getModel() {
        return model;
    }

    @Override
    public String getBatarya() {
        return batarya;
    }

    @Override
    public int getEn() {
        return en;
    }

    @Override
    public int getBoy() {
        return boy;
    }
    
}

Constructor ekleyelim.

public class S8 implements Telefon {

    private String model;
    private String batarya;
    private int en;
    private int boy;

    public S8(String model, String batarya, int en, int boy) {
        this.model = model;
        this.batarya = batarya;
        this.en = en;
        this.boy = boy;
    }

    @Override
    public String getModel() {
        return model;
    }

    @Override
    public String getBatarya() {
        return batarya;
    }

    @Override
    public int getEn() {
        return en;
    }

    @Override
    public int getBoy() {
        return boy;
    }
    
}

Burada bir de toString() metodunu ezelim. Daha sonra bunu hangi nesneyi oluşturduğumuzu göstermesi için kullanıırız.

public class S8 implements Telefon {

    private String model;
    private String batarya;
    private int en;
    private int boy;

    public S8(String model, String batarya, int en, int boy) {
        this.model = model;
        this.batarya = batarya;
        this.en = en;
        this.boy = boy;
    }

    @Override
    public String getModel() {
        return model;
    }

    @Override
    public String getBatarya() {
        return batarya;
    }

    @Override
    public int getEn() {
        return en;
    }

    @Override
    public int getBoy() {
        return boy;
    }

    @Override
    public String toString() {
        return "S8{" +
                "model='" + model + '\'' +
                ", batarya='" + batarya + '\'' +
                ", en=" + en +
                ", boy=" + boy +
                '}';
    }
}

Hemen hemen aynı şeyler yapılacağı için s8 I kopyalayalım ve note8 I oluşturalım.

public class Note8 implements Telefon {

    private String model;
    private String batarya;
    private int en;
    private int boy;

    public Note8(String model, String batarya, int en, int boy) {
        this.model = model;
        this.batarya = batarya;
        this.en = en;
        this.boy = boy;
    }

    @Override
    public String getModel() {
        return model;
    }

    @Override
    public String getBatarya() {
        return batarya;
    }

    @Override
    public int getEn() {
        return en;
    }

    @Override
    public int getBoy() {
        return boy;
    }

    @Override
    public String toString() {
        return "Note8{" +
                "model='" + model + '\'' +
                ", batarya='" + batarya + '\'' +
                ", en=" + en +
                ", boy=" + boy +
                '}';
    }
}

Şimdi normalde bu işi bayiler yapıyor olsaydı, “new S8(…)” ya da “new Note8(…)” diyerek oluşturabileceklerdi. Fakat biz istiyoruz ki, bayiler değil de, bu işi yapan fabrikalar bu görevi üstlensin. O zaman “TelefonFabrikasi” adında bir classa ihtiyacımız var.

Bu classın getTelefon() adında static bir metodu olsun.

Neden static olsun dedim? Çünkü bayiler telefon oluşturmasın derken, fabrika da oluşturmasınlar. Fabrika üzerinden direk static metodu çağıralım, yeterli. Amacımız biliyorsunuz zaten nesneyi oluşturma görevini fabrikaya verip, bayilerle telefon arasındaki ilişkiyi minimum bağımlılıkla kurmak.

Parametre olarak model, batarya, en ve boy alsın ve bana telefon dönsün. Telefon biliyorsunuz interface.

public class TelefonFabrikasi {

    public static Telefon getTelefon(String model, String batarya, int en, int boy){

        Telefon telefon = telefon = new S8(model, batarya, en, boy);
       
        return telefon;
    }
}

Ardından getTelefon() metodu içinde “model” ne imiş bakalım. Ona göre de telefonu dönelim.

public class TelefonFabrikasi {

    public static Telefon getTelefon(String model, String batarya, int en, int boy){

        Telefon telefon;
        if ("S8".equalsIgnoreCase(model)){
            telefon = new S8(model, batarya, en, boy);
        } else if ("Note8".equalsIgnoreCase(model)){
            telefon = new Note8(model, batarya, en, boy);
        } else {
            throw new RuntimeException("Geçerli bir model değildir!");
        }

        return telefon;
    }
}

Şimdi de fabrika sınıfımızı kullanan bayileri oluşturalım. TelefonBayi adında bir sınıf daha oluşturalım ve bu bayiler fabrikalarımızdan  telefon istesinler.

public class TelefonBayi {

    public static void main(String[] args) {

        Telefon s8 = TelefonFabrikasi.getTelefon("s8", "2600mah", 4, 7);

        Telefon note8 = TelefonFabrikasi.getTelefon("note8", "3000mah", 5, 8);

        System.out.println("S8 için telefon özellikleri: ");
        System.out.println(s8);

        System.out.println("Note8 için telefon özellikleri: ");
        System.out.println(note8);
    }
}

Ugulamamızı çalıştıralım ve görelim.

Çıktı:

S8 için telefon özellikleri:
S8{model=’s8′, batarya=’2600mah’, en=4, boy=7}
Note8 için telefon özellikleri:
Note8{model=’note8′, batarya=’3000mah’, en=5, boy=8}

Görüldüğü gibi bayiler herhangi bir nesne oluşturmadan telefona ulaşabildi.

Burada telefon sınıfı abstract bir sınıf olamaz mıydı? Evet olabilirdi. Ya da concrete(somut) sınıf olabilir miydi? Evet olabilirdi.  İhtiyacınıza göre bu ikisi de olabilirdi.

Bu kalıbın bir de dezavantajı var. Nedir bu?

Samsung un yüzlerce modeli var. Bizler factory metodu içinde her model için if else mi yazacağız? Yazdığımızı düşünelim ve sonrasında da o koddaki karmaşayı bir düşünelim.

Bu karmaşa da düşnülmüş ve “Abstact Factroty” kalıbı doğmuş. Bir sonraki yazıda da “Abstact Factory Tasarım Kalıbı” nı inceleyeceğiz.

Tarih:JavaTasarım Kalıpları

İlk Yorumu Siz Yapın

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir