Menu
Coddy logo textTech

Fabrika Kalıbı

Coddy'nin C Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 55 / 61.

Factory deseni, nesne oluşturmayı tek bir fonksiyonda merkezileştirir. Programınızın her yerine malloc ve başlatma kodu dağıtmak yerine, ne oluşturulacağına karar veren ve kullanıma hazır bir nesne döndüren tek bir fonksiyonu çağırırsınız.

Bu desen, polimorfizm ile birleştirildiğinde özellikle güçlüdür. Bir fabrika, ortak bir temel işaretçi aracılığıyla farklı somut türler döndürebilir ve oluşturma ayrıntılarını çağırandan gizleyebilir. Çağıran sadece "bir şekil" ister ve fabrika bir daire mi, dikdörtgen mi yoksa başka bir şey mi inşa edeceğine karar verir.

İşte tipik bir factory uygulaması:

typedef enum {
    SHAPE_CIRCLE,
    SHAPE_RECTANGLE
} ShapeType;

Shape* create_shape(ShapeType type) {
    switch (type) {
        case SHAPE_CIRCLE:
            return (Shape*)create_circle(5.0);
        case SHAPE_RECTANGLE:
            return (Shape*)create_rectangle(4.0, 3.0);
        default:
            return NULL;
    }
}

Fabrika bir tanımlayıcı (genellikle bir enum) alır ve hangi kurucunun çağrılacağını belirlemek için bir switch ifadesi kullanır. Oluşturulan gerçek türden bağımsız olarak bir Shape* döndürür. Çağıranın Circle veya Rectangle hakkında bilgi sahibi olmasına gerek yoktur — sadece temel tür ile çalışır:

Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s);  // polimorfik çağrı
free_shape(s);

Bu desen yeni türler eklemeyi kolaylaştırır: sadece yeni bir enum değeri ve factory içinde yeni bir case ekleyin. Kodunuzun geri kalanı değişmeden kalır.

challenge icon

Görev

Kolay

Hadi bir Pet Factory (Evcil Hayvan Fabrikası) inşa edelim — tek bir fabrika fonksiyonu aracılığıyla farklı türde evcil hayvanlar oluşturan bir sistem. Oluşturma mantığını kodunuzun her yerine dağıtmak yerine, bir girdi tanımlayıcısına göre ne tür bir evcil hayvan oluşturulacağına karar veren tek bir yerde merkezileştireceksiniz.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • pet.h: PET_DOG, PET_CAT ve PET_BIRD değerlerine sahip bir PetType enum'ı tanımlayın. speak (bir const Pet* alan ve hiçbir şey döndürmeyen) için bir fonksiyon göstericisi içeren temel bir Pet struct'ı oluşturun. Bir PetType alan ve bir Pet* döndüren create_pet fabrika fonksiyonunu ve temizlik için bir free_pet fonksiyonunu deklare edin.
  • pet.c: Her biri ilk üyesi olarak Pet içeren üç somut evcil hayvan struct'ı — Dog, Cat ve Bird — tanımlayın. Her tür için bir speak fonksiyonu uygulayın:
    • Köpekler şunu yazdırır: Woof!
    • Kediler şunu yazdırır: Meow!
    • Kuşlar şunu yazdırır: Tweet!
    Her evcil hayvan türü için bellek ayıran ve uygun speak fonksiyonunu bağlayan yapıcı (constructor) fonksiyonlar oluşturun. Ardından create_pet fabrikasını uygulayın — doğru yapıcıyı çağırmak ve sonucu bir Pet* olarak döndürmek için PetType üzerinde bir switch ifadesi kullanın. Geçersiz türler için NULL döndürün. Ayrılan belleği serbest bırakmak için free_pet fonksiyonunu uygulayın.
  • main.c: Evcil hayvan türünü temsil eden bir tam sayı okuyun (köpek için 0, kedi için 1, kuş için 2). Uygun evcil hayvanı oluşturmak için fabrikanızı kullanın, temel Pet* göstericisi aracılığıyla speak fonksiyonunu polimorfik olarak çağırın ve ardından evcil hayvanı serbest bırakın.

Programınız bir girdi alacaktır: hangi evcil hayvanın oluşturulacağını belirten bir tam sayı.

Girdi 0 olduğunda örnek çıktı:

Woof!

Girdi 1 olduğunda örnek çıktı:

Meow!

Girdi 2 olduğunda örnek çıktı:

Tweet!

Factory deseninin güzelliği, main.c dosyasının Dog, Cat veya Bird struct'ları hakkında bilgi sahibi olmasına gerek duymamasıdır — sadece temel Pet türüyle çalışır. Daha sonra yeni bir evcil hayvan türü eklemek, evcil hayvanları kullanan hiçbir kodu değiştirmeden yeni bir enum değeri ve fabrikada yeni bir case eklemek anlamına gelir.

Kopya kağıdı

Factory deseni, nesne oluşturmayı tek bir fonksiyonda merkezileştirerek oluşturma ayrıntılarını çağırandan gizler.

Bir factory fonksiyonu, bir tanımlayıcı (genellikle bir enum) alır ve hangi kurucunun çağrılacağını belirlemek için bir switch ifadesi kullanarak bir temel tür işaretçisi döndürür:

typedef enum {
    SHAPE_CIRCLE,
    SHAPE_RECTANGLE
} ShapeType;

Shape* create_shape(ShapeType type) {
    switch (type) {
        case SHAPE_CIRCLE:
            return (Shape*)create_circle(5.0);
        case SHAPE_RECTANGLE:
            return (Shape*)create_rectangle(4.0, 3.0);
        default:
            return NULL;
    }
}

Çağıran taraf yalnızca temel türle çalışır, bu da polimorfik davranışı mümkün kılar:

Shape* s = create_shape(SHAPE_CIRCLE);
s->draw(s);  // polimorfik çağrı
free_shape(s);

Avantajları: Yeni türler eklemek, factory'yi kullanan mevcut kodu değiştirmeden yalnızca yeni bir enum değeri ve switch durumu eklemeyi gerektirir.

Kendin dene

#include <stdio.h>
#include "pet.h"

int main(void) {
    int type;
    scanf("%d", &type);
    
    // TODO: Uygun evcil hayvanı oluşturmak için fabrikayı kullanın
    // Hint: int değerini PetType türüne dönüştürün
    
    // TODO: speak fonksiyonunu Pet* işaretçisi üzerinden polimorfik olarak çağırın
    
    // TODO: Evcil hayvanı serbest bırakın
    
    return 0;
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Object Oriented Programming bölümündeki tüm dersler