January 19, 2026 (7mo ago) — last updated July 19, 2026 (1mo ago)

TypeScript Singleton Rehberi

TypeScript’te Singleton deseni: ne zaman kullanılmalı, TypeScript örnekleri, test etkileri ve bağımlılık enjeksiyonuna geçiş adımlarıyla kapsamlı rehber.

← Back to blog
Cover Image for TypeScript Singleton Rehberi

Singleton deseni, bir sınıfın yalnızca tek bir örneğe sahip olmasını ve bu örneğe uygulamanın her yerinden tutarlı biçimde erişilmesini sağlar. Bu rehberde TypeScript örnekleri, avantajlar/dezavantajlar, test etkileri ve DI gibi modern alternatifleri adım adım ele alıyoruz.

TypeScript Singleton Rehberi

Taht takan bir yazmanın tacıyla bir parşömeni dikkatle inceleyen kurşunkalem eskizi.

Yazılım geliştirmede bazı desenler güçlü ama tartışmalıdır. Singleton deseni de bunlardan biridir: bir sınıfın yalnızca tek bir örneğe sahip olmasını sağlar ve bu örneğe uygulamanın her yerinden erişmek için tek, iyi bilinen bir yol sunar.1

Bu desen, merkezi bir yapılandırma yöneticisi veya tek bir günlükleme servisi gibi gerçekten benzersiz olması gereken kaynaklarda işe yarar. Birden fazla, çelişen yapılandırma nesnesinin veya birbirleriyle yarışan günlükleyici örneklerinin olması yerine, tek bir örnek düzen sağlar, bellek kullanımını azaltır ve paylaşılmış kaynaklara erişimi kontrol altına alır.

Nedir, Ne Zaman Kullanılır?

Düşünün ki bir krallığın sadece bir resmi yazmanı var; tüm resmi kayıtlar onun defterinde tutuluyor. Eğer herkes yazman olmaya karar verseydi, kayıtlar çelişir ve karışıklık artardı. Singleton deseni yazılım içinde aynı işi yapar: bir sınıfın tek bir örneğini zorunlu kılar ve o örneğe küresel bir erişim noktası sağlar.

Temel olarak, Singleton şu durumlarda uygundur:

  • Gerçekten benzersiz bir kaynağa erişim gerekiyorsa (ör. donanım arayüzü).
  • Birden çok örneğin zararlı olacağı pahalı kaynaklar (ör. veritabanı bağlantı havuzu).
  • Merkezi, uygulama çapında tutarlı konfigürasyon veya günlükleme gerektiğinde.

Öte yandan, Singleton gizli bağımlılık ve küresel durum riskleri getirir; bu yüzden kullanmadan önce test edilebilirlik ve sürdürülebilirlik maliyetlerini değerlendirin.

Temel İlkeler

ÖzellikAçıklama
Tek örnekSınıf, uygulama süresince yalnızca bir örneğe izin verir; genellikle private constructor ile sağlanır.
Küresel erişimStatik bir yöntem (ör. getInstance()) tek erişim yolunu sunar.
Tembel başlatmaÖrnek genellikle ilk istek geldiğinde oluşturulur; bu başlangıç maliyetini düşürebilir.
Durum yönetimiUygulama ayarları veya oturum gibi merkezi durum için kullanılır.

Ne Zaman Kaçınılmalı?

Singleton’lar sıkı bağımlılığa yol açabilir; sınıflar bağımlılıklarını imzalarında göstermeyebilir. Bu durum test etmeyi zorlaştırır ve beklenmeyen yan etkilere neden olabilir. Modern mimarilerde Bağımlılık Enjeksiyonu (DI) ve kompozisyon kökü yaklaşımları genellikle daha sürdürülebilir alternatifler sunar.

Pratik TypeScript Örneği

Soyuttan pratiğe geçelim: TypeScript ile tür güvenli, basit bir Singleton uygulaması görelim. TypeScript’in yaygın kullanımı, bu tür desenleri tür güvenliğiyle uygulamayı cazip kılıyor6.

class ConfigManager {
  private static instance: ConfigManager;
  private settings: Map<string, any> = new Map();

  private constructor() {
    console.log("Initializing ConfigManager instance...");
    this.settings.set("API_URL", "https://api.example.com");
    this.settings.set("TIMEOUT", 5000);
  }

  public static getInstance(): ConfigManager {
    if (!ConfigManager.instance) {
      ConfigManager.instance = new ConfigManager();
    }
    return ConfigManager.instance;
  }

  public get(key: string): any {
    return this.settings.get(key);
  }
}

// const config = new ConfigManager(); // Error: Constructor of class 'ConfigManager' is private.

Bu yapı, private constructor ile yeni örnek yaratılmasını engeller ve statik getInstance ile tembel başlatmayı sağlar. Aşağıda bu ConfigManager’ı kullanan basit bir servis örneği var.

class ApiService {
  private apiUrl: string;

  constructor() {
    const config = ConfigManager.getInstance();
    this.apiUrl = config.get("API_URL");
    console.log(`ApiService initialized with API URL: ${this.apiUrl}`);
  }

  public fetchData(): void {
    console.log(`Fetching data from ${this.apiUrl}...`);
  }
}

console.log("Application starting...");
const service1 = new ApiService();
service1.fetchData();
const service2 = new ApiService();
console.log("Application finished.");

Çıktıda ConfigManager’ın başlatma mesajını yalnızca bir kez görmelisiniz; bu, her iki servisin aynı örneği kullandığını gösterir.

Yararlar ve Dezavantajlar

Yararlar:

  • Küresel erişim, modüller arası kullanımı basitleştirir.
  • Tembel başlatma ile başlangıç maliyeti düşürülebilir.
  • Pahalı kaynakların tekrarlanmasını önler.

Dezavantajlar:

  • Gizli bağımlılık ve sıkı bağlanma (tight coupling).
  • Küresel değiştirilebilir durum nedeniyle zor yakalanan hatalar.
  • Birim testlerinde durum sızmasına ve taklit (mock) güçlüğüne yol açabilir.

Testlerde sıkıntı yaşanıyorsa, arayüz (interface) tanıtıp DI ile geçiş yapmak genellikle en iyi yaklaşımdır.

Test ve Eşzamanlılık Konuları

Durum tutan Singleton’lar, eşzamanlı ortamda yarış koşullarına yol açabilir. Örneğin iki paralel isteğin aynı sayacı güncellemesi beklenmeyen sonuçlar doğurabilir. Bu yüzden thread-safety veya senkronizasyon stratejileri düşünülmelidir.

Ayrıca, Singleton’lar birim testlerini kırılgan hale getirebilir; testler arasında global durum sızması olabilir. Bağımlılık Enjeksiyonu kullanmak, test double’ların (mock/fake) doğrudan gönderilmesine izin verdiği için testleri stabil hale getirir.3

Modern Alternatifler: DI ve IoC

Bağımlılık Enjeksiyonu (DI) Singleton’ın getirdiği gizli bağımlılık sorununu çözmek için tercih edilen yaklaşımdır. Bir servis, gereken bağımlılığı yapıcı (constructor) parametresi olarak aldığında, bağımlılığı testlerde kolayca değiştirilebilir.

Örnek:

interface IConfigManager { get(key: string): any }

class ApiService {
  private apiUrl: string;
  constructor(config: IConfigManager) { this.apiUrl = config.get("API_URL"); }
}

Popüler TypeScript çerçeveleri NestJS ve Angular yerleşik DI sağlar; genel projeler için InversifyJS gibi kütüphaneler kullanılabilir45. Ayrıca TypeScript ve ekosistemin büyümesi DI gibi modern yaklaşımları benimsemeyi kolaylaştırıyor7.

Miras Kod Tabanında Kademeli Refaktör

  1. Singleton çağrılarının nerede olduğunu tespit edin ve sorumluluk sınırlarını belirleyin.
  2. Bir arayüz tanımlayın ve tüketicileri birer birer arayüzü kabul edecek şekilde refaktörleyin.
  3. Kompozisyon kökünde tek örneği oluşturun veya bir DI konteynerine bırakın.

Bu adım adım yaklaşım, uygulamayı kırmadan gizli bağlanmayı azaltır ve test edilebilirliği artırır.

Önemli Çıkarımlar

  • Singleton’ları ancak gerçekten benzersiz olması gereken servisler için kullanın.
  • Test edilebilirlik için DI’ı tercih edin.
  • Singleton kullanılıyorsa, tembel başlatma, eşzamanlılık ve thread-safety konularına dikkat edin.
  • Miras projelerde kademeli refaktör yaparak gizli bağlanmayı azaltın.

SSS — Hızlı Soru&Cevap

S: Singleton ne zaman uygundur? C: Bir kaynak gerçekten benzersizse, örn. merkezi logger veya donanım adaptörü. Mümkünse DI’ı tercih edin.

S: Şimdi Singleton kullanan kodu nasıl test ederim? C: Bir arayüz tanımlayıp tüketicileri arayüzü kabul edecek şekilde refaktörleyin; testlerde sahte (fake) örnekler enjeksiyonuyla test edin.

S: Miras bir uygulamadan Singleton’ları çıkarmanın güvenli yolu nedir? C: Kullanımları haritalayın, arayüzler oluşturun, tüketicileri kademeli olarak refaktörleyin ve kompozisyon kökünde tek örnek sağlayın veya DI konteyneri kullanın.

Hızlı Q&A — Kısa ve Öz

1) Singleton’ı hemen kaldırmalı mıyım? Hayır. Eğer servis gerçekten tek ve paylaşılıyorsa, kullanmaya devam edin ama arayüzler ve test double’larla korun.

2) DI her zaman daha mı iyi? Genellikle evet; DI test edilebilirliği ve gevşek bağlanmayı destekler. Ancak basit, durumsuz araçlar için küçük Singleton’lar makul olabilir.

3) Eşzamanlılık sorunlarını nasıl azaltırım? Paylaşılan durumu minimize edin, atomik operasyonlar veya senkronizasyon kullanın, veya Stateful nesneleri kapsamlı (scoped) örneklere taşıyın.


1.
Martin Fowler, “Singleton,” Bliki, https://martinfowler.com/bliki/Singleton.html
2.
3.
Mark Seemann, “Singletons Are Pathological Liars,” https://blog.ploeh.dk/2010/07/28/SingletonsArePathologicalLiar/
4.
NestJS Documentation, “Dependency Injection,” https://docs.nestjs.com/fundamentals/injection
5.
InversifyJS Documentation, https://inversify.io/
6.
State of JS 2020, “TypeScript” — anket sonuçları ve kullanım trendleri, https://2020.stateofjs.com/en-US/technologies/languages/typescript/
7.
GitHub Octoverse, “The State of the Octoverse” — TypeScript’in hızla büyüyen diller arasında olduğuna dair rapor, https://octoverse.github.com/
← Back to blog
🙋🏻‍♂️

AI kod yazar.
Siz onu uzun süre dayanır hale getirirsiniz.

AI hızlanması çağında, temiz kod sadece iyi bir uygulama değil — ölçeklenen sistemlerle kendi ağırlığı altında çöken kod tabanları arasındaki farktır.

TypeScript Singleton Rehberi | Clean Code Guy