
Factory Functions
Giriş
Önceki makalede OOP'nin temel fikrini öğrendik: benzer nesneler üretmek için şablonlar kullanmak. Peki bu şablonları nasıl oluştururuz?
JavaScript'te nesne şablonu oluşturmanın ilk ve en basit yolu Factory Functions - yani "fabrika fonksiyonları"dır. Adından da anlaşılacağı gibi, bu fonksiyonlar bir fabrika gibi çalışır: malzeme verirsiniz, size ürün (nesne) üretir.
Factory Function Nedir?
Factory Function, çağrıldığında yeni bir nesne oluşturup döndüren fonksiyondur.
// En basit factory function
function kullaniciOlustur(ad, yas) {
return {
ad: ad,
yas: yas
};
}
// Kullanım
const kullanici1 = kullaniciOlustur("Ahmet", 25);
const kullanici2 = kullaniciOlustur("Ayşe", 30);
console.log(kullanici1); // {ad: "Ahmet", yas: 25}
console.log(kullanici2); // {ad: "Ayşe", yas: 30}Fabrika Analojisi
┌─────────────────────────────┐
│ kullaniciOlustur() │
│ FABRİKA │
└─────────────────────────────┘
│
┌──────────────┼──────────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│Ahmet,25│ │Ayşe,30 │ │Ali,28 │
└────────┘ └────────┘ └────────┘
Aynı fabrika, farklı parametrelerle farklı ürünler üretirAdım Adım Factory Function
Adım 1: Sadece Özellikler
function kitapOlustur(baslik, yazar, sayfa) {
const kitap = {}; // Boş nesne oluştur
kitap.baslik = baslik;
kitap.yazar = yazar;
kitap.sayfa = sayfa;
return kitap; // Nesneyi döndür
}
const kitap1 = kitapOlustur("1984", "George Orwell", 328);
console.log(kitap1);
// {baslik: "1984", yazar: "George Orwell", sayfa: 328}Adım 2: Kısa Yazım (ES6)
ES6 ile property shorthand kullanabiliriz:
function kitapOlustur(baslik, yazar, sayfa) {
return {
baslik, // baslik: baslik yerine
yazar, // yazar: yazar yerine
sayfa // sayfa: sayfa yerine
};
}Adım 3: Metot Ekleme
function kitapOlustur(baslik, yazar, sayfa) {
return {
baslik,
yazar,
sayfa,
okunanSayfa: 0,
// Metotlar
bilgiGoster() {
console.log(`${this.baslik} - ${this.yazar}`);
},
oku(sayfaSayisi) {
this.okunanSayfa += sayfaSayisi;
console.log(`${sayfaSayisi} sayfa okudunuz. Toplam: ${this.okunanSayfa}/${this.sayfa}`);
},
tamamlandiMi() {
return this.okunanSayfa >= this.sayfa;
}
};
}Kullanım
const kitap = kitapOlustur("Suç ve Ceza", "Dostoyevski", 671);
kitap.bilgiGoster(); // Suç ve Ceza - Dostoyevski
kitap.oku(50); // 50 sayfa okudunuz. Toplam: 50/671
kitap.oku(100); // 100 sayfa okudunuz. Toplam: 150/671
console.log(kitap.tamamlandiMi()); // falsethis Keyword
Factory function içindeki metotlarda this kullanıyoruz. Peki this neyi ifade eder?
function oyuncuOlustur(isim, skor) {
return {
isim,
skor,
puanKazan(puan) {
this.skor += puan; // this = bu nesne
console.log(`${this.isim} ${puan} puan kazandı!`);
},
durumGoster() {
console.log(this); // Tüm nesneyi gösterir
}
};
}
const oyuncu1 = oyuncuOlustur("Zeynep", 0);
oyuncu1.puanKazan(10); // Zeynep 10 puan kazandı!
oyuncu1.durumGoster(); // {isim: "Zeynep", skor: 10, puanKazan: ƒ, durumGoster: ƒ}this Nasıl Çalışır?
oyuncu1.puanKazan(10);
// ↑
// │
// this, noktanın solundaki nesneyi ifade eder
// Yani: this = oyuncu1Pratik Örnek: Hesap Makinesi
function hesapMakinesiOlustur() {
return {
sonuc: 0,
gecmis: [],
topla(sayi) {
this.sonuc += sayi;
this.gecmis.push(`+${sayi}`);
return this; // Zincirleme için
},
cikar(sayi) {
this.sonuc -= sayi;
this.gecmis.push(`-${sayi}`);
return this;
},
carp(sayi) {
this.sonuc *= sayi;
this.gecmis.push(`×${sayi}`);
return this;
},
bol(sayi) {
if (sayi === 0) {
console.log("Sıfıra bölünemez!");
return this;
}
this.sonuc /= sayi;
this.gecmis.push(`÷${sayi}`);
return this;
},
sifirla() {
this.sonuc = 0;
this.gecmis = [];
return this;
},
sonucuAl() {
return this.sonuc;
},
gecmisiGoster() {
console.log("İşlemler:", this.gecmis.join(" "));
console.log("Sonuç:", this.sonuc);
}
};
}
// Kullanım
const hesap = hesapMakinesiOlustur();
hesap.topla(10);
hesap.carp(5);
hesap.cikar(20);
hesap.bol(2);
hesap.gecmisiGoster();
// İşlemler: +10 ×5 -20 ÷2
// Sonuç: 15
// Zincirleme kullanım (method chaining)
hesap.sifirla().topla(100).cikar(30).carp(2).gecmisiGoster();
// İşlemler: +100 -30 ×2
// Sonuç: 140Pratik Örnek: Ürün Yönetimi
function urunOlustur(ad, fiyat, stok) {
return {
ad,
fiyat,
stok,
satisAdedi: 0,
bilgiGoster() {
console.log(`
Ürün: ${this.ad}
Fiyat: ${this.fiyat} TL
Stok: ${this.stok} adet
Satış: ${this.satisAdedi} adet
`);
},
spipleşmek(adet) {
if (adet > this.stok) {
console.log(`Yetersiz stok! Mevcut: ${this.stok}`);
return false;
}
this.stok -= adet;
this.satisAdedi += adet;
console.log(`${adet} adet ${this.ad} satıldı.`);
return true;
},
stokEkle(adet) {
this.stok += adet;
console.log(`${adet} adet eklendi. Yeni stok: ${this.stok}`);
},
indirimUygula(yuzde) {
const indirim = this.fiyat * (yuzde / 100);
this.fiyat -= indirim;
console.log(`%${yuzde} indirim! Yeni fiyat: ${this.fiyat} TL`);
},
toplamSatisGetirisi() {
return this.satisAdedi * this.fiyat;
}
};
}
// Kullanım
const telefon = urunOlustur("iPhone 15", 45000, 50);
const kulaklik = urunOlustur("AirPods Pro", 8000, 100);
telefon.spipleşmek(5); // 5 adet iPhone 15 satıldı.
telefon.indirimUygula(10); // %10 indirim! Yeni fiyat: 40500 TL
telefon.bilgiGoster();
kulaklik.spipleşmek(200); // Yetersiz stok! Mevcut: 100
kulaklik.stokEkle(50); // 50 adet eklendi. Yeni stok: 150Factory Function'ın Avantajları
1. Basitlik
// Anlaşılması ve yazması kolay
function noktaOlustur(x, y) {
return { x, y };
}2. new Keyword Gerektirmez
// Factory function
const nokta1 = noktaOlustur(10, 20); // ✓ Doğrudan çağır
// Constructor function (ileride göreceğiz)
const nokta2 = new Nokta(10, 20); // new gerekli3. Özel (Private) Değişkenler
Closure kullanarak gizli değişkenler oluşturabilirsiniz:
function sayacOlustur() {
let sayac = 0; // Dışarıdan erişilemez!
return {
artir() {
sayac++;
console.log(sayac);
},
azalt() {
sayac--;
console.log(sayac);
},
degerAl() {
return sayac;
}
};
}
const sayac = sayacOlustur();
sayac.artir(); // 1
sayac.artir(); // 2
sayac.artir(); // 3
sayac.azalt(); // 2
console.log(sayac.sayac); // undefined - Erişilemez!
console.log(sayac.degerAl()); // 2 - Sadece metotla erişilebilirFactory Function'ın Dezavantajı: Hafıza Sorunu
İşte kritik nokta! Her factory function çağrısında metotların yeni kopyaları oluşturulur:
function kullaniciOlustur(ad) {
return {
ad,
selamla() {
console.log(`Merhaba, ben ${this.ad}`);
}
};
}
const user1 = kullaniciOlustur("Ali");
const user2 = kullaniciOlustur("Veli");
// Her nesnenin kendi selamla kopyası var!
console.log(user1.selamla === user2.selamla); // falseGörsel Temsil
Factory Function ile:
┌─────────────────┐ ┌─────────────────┐
│ user1 │ │ user2 │
├─────────────────┤ ├─────────────────┤
│ ad: "Ali" │ │ ad: "Veli" │
│ selamla: ƒ ──────── │ selamla: ƒ ──────── Her birinin
└─────────────────┘ │ └─────────────────┘ │ AYRI kopyası!
│ │
▼ ▼
function() {...} function() {...}
(Kopya 1) (Kopya 2)Prototype ile (İdeal):
┌─────────────────┐ ┌─────────────────┐
│ user1 │ │ user2 │
├─────────────────┤ ├─────────────────┤
│ ad: "Ali" │ │ ad: "Veli" │
│ __proto__: ─────┼─────┼─────────────────┼────┐
└─────────────────┘ └─────────────────┘ │
│
▼
┌───────────────────┐
│ Prototype │
│ selamla: ƒ │
└───────────────────┘
(Tek kopya, paylaşılır)Hafıza Karşılaştırması
// 1000 kullanıcı oluşturduğumuzu düşünelim
// Factory Function ile:
// 1000 x selamla() fonksiyonu = 1000 kopya 😱
// Prototype ile:
// 1 x selamla() fonksiyonu = 1 kopya ✓
// (Tüm kullanıcılar aynı prototype'ı paylaşır)Ne Zaman Factory Function Kullanmalı?
Kullanın ✓
- Basit, az metotlu nesneler için
- Private değişkenler gerektiğinde
newkeyword'ünden kaçınmak istediğinizde- Hızlı prototipleme yaparken
Kullanmayın ✗
- Çok sayıda nesne üretecekseniz
- Metotları paylaşmak istiyorsanız
- Performans kritikse
- Inheritance (miras) kullanacaksanız
Özet
// Factory Function şablonu
function nesneOlustur(param1, param2) {
return {
// Özellikler
ozellik1: param1,
ozellik2: param2,
// Metotlar
metot1() {
// this.ozellik1 kullanarak işlem yap
},
metot2() {
// this.ozellik2 kullanarak işlem yap
}
};
}
// Kullanım
const nesne = nesneOlustur(deger1, deger2);
nesne.metot1();| Özellik | Açıklama |
|---|---|
| Tanım | Nesne üreten ve döndüren fonksiyon |
| Avantaj | Basit, new gerektirmez, private değişkenler |
| Dezavantaj | Her nesne metotların kopyasını taşır (hafıza israfı) |
| this | Metot içinde nesnenin kendisini ifade eder |
Sırada Ne Var?
Factory function'ların hafıza sorununu gördük. Her nesne metotların kopyasını taşıyor - bu ideal değil.
Bir sonraki makalede Constructor Functions ve new keyword'ünü öğreneceğiz. Bu yöntem prototype'ı kullanarak metotları paylaştırır ve hafıza sorununu çözer.


