December 20, 2025 (8mo ago) — last updated August 21, 2026 (2d ago)

TypeScript OOP Tasarım Desenleri — Pratik Örnekler

TypeScript örnekleriyle OOP tasarım desenlerini öğrenin: Singleton, Factory, Adapter, Observer ve Strategy; refaktoring ve uygulama ipuçlarıyla kodunuzu iyileştirin.

← Back to blog
Cover Image for TypeScript OOP Tasarım Desenleri — Pratik Örnekler

Nesne yönelimli tasarım desenleri, tekrar eden mimari sorunlara kanıtlanmış çözümler sunar. Bu rehber TypeScript örnekleriyle Singleton, Factory, Adapter, Observer ve Strategy gibi temel desenleri gösterir; amacımız kodunuzu daha okunabilir, test edilebilir ve genişletilebilir hâle getirecek pratik yaklaşımlar sunmaktır.

TypeScript OOP Tasarım Desenleri — Pratik Örnekler

Rehberimizle tasarım desenleri konusunda ustalaşın. Oluşturucu, yapısal ve davranışsal desenleri TypeScript örnekleriyle öğrenin; bakım, test ve genişletilebilirlik becerilerinizi hızla artırın.

Giriş

Nesne yönelimli programlamada tasarım desenleri, tekrar eden tasarım zorluklarına uygulanabilir çözümler sunar ve ekipler arasında ortak bir dil sağlar. Bu rehberde Singleton, Factory, Adapter, Observer ve Strategy gibi temel desenleri TypeScript örnekleriyle göreceksiniz; kodunuzu daha okunabilir, test edilebilir ve genişletilebilir hâle getirecek pratik ipuçları bulacaksınız. TypeScript’in benimsenmesi hızla artıyor ve bu dil OOP desenlerini güvenle uygulamak için güçlü araçlar sunuyor1.

Tasarım Desenleri Nedir ve Neden Önemlidir

Plan olmadan karmaşık bir sistemi inşa etmek zordur. Tasarım desenleri, sık tekrar eden mimari problemler için test edilmiş şablonlar sunar ve ekiplerin niyetlerini hızlıca paylaşmasını sağlar. “Factory” veya “Singleton” dediğinizde ekip üyeleri tasarımın amacını anlar; bu da işbirliğini ve bakım süreçlerini hızlandırır. Gang of Four kitabı bu sınıflandırmanın temel kaynağıdır ve desenlerin neden işe yaradığını anlamak için hâlâ başvurulan bir kaynaktır2.

Tasarım Deseni Kategorileri

Gang of Four desenleri üç ana gruba ayrılır: oluşturucu, yapısal ve davranışsal. Hangi kategoriye bakacağınızı bilmek, doğru çözümü daha hızlı seçmenize yardımcı olur.

Oluşturucu, yapısal ve davranışsal tasarım desenlerini basit kutu illüstrasyonlarıyla gösteren diyagram.

Kısa Özet

Desen KategorisiTemel AmaçYaygın Örnekler
OluşturucuNesne oluşturmayı yönetme ve soyutlamaFactory, Builder, Singleton, Prototype
YapısalSınıfları ve nesneleri daha büyük, esnek yapılara birleştirmeAdapter, Decorator, Facade, Composite
DavranışsalNesnelerin nasıl etkileştiğini ve iletişim kurduğunu tanımlamaObserver, Strategy, Command, Iterator

Oluşturucu Desenler: Nesne Oluşturmayı Kontrol Etme

Oluşturucu desenler, nesne oluşturma mantığını saklayarak istemci kodun somut sınıflara sıkı şekilde bağlı olmasını engeller.

Singleton — Tek Bir Örnek Sağlama

Singleton, bir sınıfın yalnızca bir örneğe sahip olmasını ve küresel bir erişim noktası sağlamasını garanti eder. Veritabanı bağlantısı veya logger gibi paylaşılan kaynaklar için kullanışlıdır; ancak küresel durum test etmeyi ve bağımlılık yönetimini zorlaştırabilir3.

Örnek: veritabanı bağlantısı için TypeScript Singleton.

class DatabaseConnection {
  private static instance: DatabaseConnection | null = null;

  private constructor() {
    // Private constructor prevents external new calls
    console.log('Connecting to the database...');
  }

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

  public query(sql: string): void {
    console.log(`Executing query: ${sql}`);
  }
}

// Usage
const db1 = DatabaseConnection.getInstance();
const db2 = DatabaseConnection.getInstance();

db1.query('SELECT * FROM users');
console.log(db1 === db2); // true

Not: Gerçekten küresel kaynaklar için Singleton kullanın; test edilebilirlik ve bağımlılık yönetimi için bağımlılık enjeksiyonunu tercih edin3.

Factory Method — Alt Sınıfların Ürünü Belirlemesine İzin Verme

Factory Method, nesne oluşturmak için bir arayüz tanımlar; alt sınıflar hangi somut ürünün örnekleneceğine karar verir. Bu yaklaşım istemci kodunu somut sınıflardan ayırarak sistemi genişletmeyi kolaylaştırır.

Örnek: işletim sistemine özgü düğmeleri render etme.

interface Button {
  render(): void;
  onClick(f: () => void): void;
}

class WindowsButton implements Button {
  render() { console.log('Rendering a button in Windows style.'); }
  onClick(f: () => void) { console.log('Windows button click event.'); f(); }
}

class MacButton implements Button {
  render() { console.log('Rendering a button in macOS style.'); }
  onClick(f: () => void) { console.log('Mac button click event.'); f(); }
}

abstract class Dialog {
  abstract createButton(): Button;

  render() {
    const okButton = this.createButton();
    okButton.render();
  }
}

class WindowsDialog extends Dialog {
  createButton(): Button { return new WindowsButton(); }
}

class MacDialog extends Dialog {
  createButton(): Button { return new MacButton(); }
}

// Client
const os: string = 'windows';
let dialog: Dialog;
if (os === 'windows') dialog = new WindowsDialog(); else dialog = new MacDialog();
dialog.render();

Factory Method, oluşturucuyu somut ürünlerden habersiz tutar; yeni platformlar kolayca eklenebilir.

Yapısal Desenler: Bileşenleri Esnek Sistemlerde Birleştirme

Yapısal desenler, nesneleri daha büyük, sağlam yapılar içinde bir araya getirmenize yardımcı olur. Aşağıda Adapter ve Decorator örnekleri var.

Elektrik adaptörünün el çizimi ve OOP tasarım desenlerini temsil eden halka yığını illüstrasyonları.

Adapter — Uyumsuz Arayüzleri Köprüleme

Adapter, uyumsuz bir arayüzü sisteminizin beklediği forma sarar. Bu, eski kodu değiştirmeden yeni kütüphaneleri entegre etmenizi sağlar.

Örnek: ModernLogger'ı mevcut ILogger arayüzüne adapte etmek.

class ModernLogger {
  public logInfo(message: string): void {
    console.log(`[INFO]: ${message}`);
  }
}

interface ILogger { log(message: string): void; }

class LoggerAdapter implements ILogger {
  private modernLogger: ModernLogger;
  constructor() { this.modernLogger = new ModernLogger(); }
  public log(message: string): void { this.modernLogger.logInfo(message); }
}

const logger: ILogger = new LoggerAdapter();
logger.log('User logged in successfully.');

Decorator — Çalışma Zamanında İşlevsellik Ekleme

Decorator, nesnelere çalışma zamanında sorumluluklar ekleyerek davranışı sarmalar. Alt sınıflamadan daha esnek bir yöntemdir ve tek sorumluluk ilkesine uygun tasarımlar sağlar.

Örnek: isteğe bağlı eklentileri olan bir abonelik bileşimi.

interface Subscription { getDescription(): string; getCost(): number; }

class BasicSubscription implements Subscription {
  getDescription(): string { return 'Basic Plan'; }
  getCost(): number { return 10; }
}

abstract class SubscriptionDecorator implements Subscription {
  protected subscription: Subscription;
  constructor(subscription: Subscription) { this.subscription = subscription; }
  abstract getDescription(): string;
  abstract getCost(): number;
}

class PremiumSupportDecorator extends SubscriptionDecorator {
  getDescription(): string { return `${this.subscription.getDescription()}, Premium Support`; }
  getCost(): number { return this.subscription.getCost() + 5; }
}

class CloudStorageDecorator extends SubscriptionDecorator {
  getDescription(): string { return `${this.subscription.getDescription()}, 1TB Cloud Storage`; }
  getCost(): number { return this.subscription.getCost() + 7; }
}

let mySubscription: Subscription = new BasicSubscription();
mySubscription = new PremiumSupportDecorator(mySubscription);
mySubscription = new CloudStorageDecorator(mySubscription);
console.log(mySubscription.getDescription());
console.log(mySubscription.getCost());

Bu bileşimsel yaklaşım özellikleri modüler ve test edilmesi kolay tutar.

Davranışsal Desenler: Nesne Etkileşimlerini Düzenleme

Davranışsal desenler, nesneler arasındaki iletişimi ve sorumluluk paylaşımını düzenler ve sistemin sürdürülebilir kalmasına yardımcı olur.

Observer — İlgilenen Tarafları Bilgilendirme

Observer, bir Subject değiştiğinde birçok gözlemcinin otomatik olarak bilgilendirilmesini sağlar. Olay tabanlı sistemler için idealdir.

Örnek: basit bir bildirim servisi.

interface Subject { attach(observer: Observer): void; detach(observer: Observer): void; notify(): void; }
interface Observer { update(subject: Subject): void; }

class NotificationService implements Subject {
  public state: string = '';
  private observers: Observer[] = [];
  attach(observer: Observer): void { this.observers.push(observer); }
  detach(observer: Observer): void { const i = this.observers.indexOf(observer); if (i !== -1) this.observers.splice(i, 1); }
  notify(): void { for (const o of this.observers) o.update(this); }
  public createNewPost(title: string): void { this.state = `New Post: ${title}`; console.log('NotificationService: A new post was created.'); this.notify(); }
}

class EmailNotifier implements Observer { public update(subject: Subject): void { if (subject instanceof NotificationService) console.log(`EmailNotifier: Sending email about "${subject.state}"`); } }
class PushNotifier implements Observer { public update(subject: Subject): void { if (subject instanceof NotificationService) console.log(`PushNotifier: Sending push notification for "${subject.state}"`); } }

const notificationService = new NotificationService();
const emailer = new EmailNotifier();
const pusher = new PushNotifier();
notificationService.attach(emailer);
notificationService.attach(pusher);
notificationService.createNewPost('Understanding Observer Pattern');
notificationService.detach(pusher);
notificationService.createNewPost('Why Strategy is Awesome');

Observer, gevşek bağlı bir tasarım üretir: Subject’in bildirdiği somut Observer’ları bilmesine gerek yoktur.

Strategy — Algoritmaları Kapsülleme

Strategy, çalışma zamanında algoritmaları takas etmenize izin verir ve büyük koşul bloklarından kaçınır. Bu yaklaşım Açık/Kapalı ilkesine uygundur4.

Örnek: bir alışveriş sepeti için ödeme stratejileri.

interface PaymentStrategy { pay(amount: number): void; }
class CreditCardStrategy implements PaymentStrategy { pay(amount: number): void { console.log(`Paying $${amount} with Credit Card.`); } }
class PayPalStrategy implements PaymentStrategy { pay(amount: number): void { console.log(`Paying $${amount} via PayPal.`); } }

class ShoppingCart {
  private paymentStrategy: PaymentStrategy;
  constructor(strategy: PaymentStrategy) { this.paymentStrategy = strategy; }
  public setPaymentStrategy(strategy: PaymentStrategy) { this.paymentStrategy = strategy; }
  public checkout(amount: number): void { this.paymentStrategy.pay(amount); }
}

const cart = new ShoppingCart(new CreditCardStrategy());
cart.checkout(150);
cart.setPaymentStrategy(new PayPalStrategy());
cart.checkout(150);

Strategy, koşullu karmaşıklığı azaltır ve sistemi genişletmeyi kolaylaştırır.

Yaygın Tuzaklar ve Refaktoring Stratejileri

Deseni seçmek işin yarısıdır; anti-pattern’lerden kaçınmak ve kod kokularını tespit etmek gerekir. Tek Sorumluluk İlkesini ihlal eden God Object gibi yapılar, uzun metotlar ve aşırı bağımlılıklar refaktoring gerektirir.

Refaktoring, dış davranışı değiştirmeden dahili yapıyı iyileştirmektir. Bu süreç miras sistemlerini güvenli şekilde yeniden düzenlemenin temel yoludur ve akademik çalışmalar desen soyutlamalarının yeniden kullanımını destekler5.

Strategy ile Refaktoring

Uzun switch veya if/else blokları bir koku göstergesidir. Bu davranışı Strategy arayüzüne çıkarmak, koşulu tek bir strateji çağrısına dönüştürür; böylece test edilebilirlik ve genişletilebilirlik artar4.

Sıkça Sorulan Sorular (Kısa ve Öz)

Q1: Hangi desenleri hemen öğrenmeliyim?

A1: Önce Singleton, Factory, Adapter, Decorator, Observer ve Strategy’yi öğrenin; bu desenler çoğu problemin çözümünde yeterlidir.

Q2: Deseni ne zaman kullanmamalıyım?

A2: Gerçek bir gereksinim yoksa desen kullanmak gereksiz karmaşıklık getirir. YAGNI prensibini uygulayın.

Q3: Tasarım desenleri fonksiyonel yaklaşımla uyumlu mu?

A3: Evet. Strategy fonksiyon parametresiyle, Decorator yüksek mertebeden fonksiyonlarla uygulanabilir.

Hızlı Soru-Cevap Özetleri

Q: Tasarım desenleri ne zaman hayat kurtarır? A: Karmaşık nesne oluşturma, platforma bağımlılık veya davranış değiş tokuşu gerektiğinde desenler mimari netlik sağlar.

Q: TypeScript desen uygularken nelere dikkat etmeli? A: Tipler ve arayüzler ile sınırları net tanımlayın; bağımlılık enjeksiyonunu tercih ederek test edilebilirliği koruyun.

Q: Refaktoring yaparken hangi sinyallere bakmalıyım? A: Uzun if/switch blokları, çok sorumluluğu olan sınıflar ve tekrar eden kod refaktoring sinyalleridir.


Clean Code Guy olarak ekiplerin sürdürülebilir yazılım inşa etmesine yardımcı oluyoruz. Kod denetimlerimiz ve AI-uyumlu refaktoring ile ekibinizin güvenle üretime geçmesini nasıl sağlayabileceğimizi keşfedin: https://cleancodeguy.com.

1.
State of JS, TypeScript adoption and ecosystem overview. https://2022.stateofjs.com/en-US/languages/
2.
Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software (Addison-Wesley, 1994). https://en.wikipedia.org/wiki/Design_Patterns
3.
Martin Fowler, “Singleton,” Bliki, discusses Singleton trade-offs and testing implications. https://martinfowler.com/bliki/Singleton.html
4.
Robert C. Martin (Uncle Bob), “The SOLID Principles,” which explain Open/Closed and related design goals. https://8thlight.com/blog/uncle-bob/2012/08/13/the-s-o-l-i-d-principles.html
5.
W. G. Griswold et al., “A Formal Foundation for Design Pattern Abstraction and Reuse,” Proceedings of ECOOP ’93, University of California, San Diego. https://cseweb.ucsd.edu/~wgg/CSE210/ecoop93-patterns.pdf
← 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.