December 20, 2025 (4mo ago) — last updated March 22, 2026 (1mo ago)

Practical OOP Design Patterns

हमारे गाइड से OOP डिज़ाइन पैटर्न सीखें—creational, structural और behavioral पैटर्न्स को TypeScript उदाहरणों के साथ समझें।

← Back to blog
Cover Image for Practical OOP Design Patterns

ऑब्जेक्ट-ओरिएंटेड डिज़ाइन पैटर्न बार-बार आने वाली समस्याओं के परखे हुए समाधान हैं। इस गाइड में creational, structural और behavioral पैटर्न्स को व्यावहारिक TypeScript उदाहरणों के साथ समझाइए गया है ताकि आप तेज़ी से बेहतर डिज़ाइन निर्णय ले सकें।

Practical OOP Design Patterns

Master design pattern OOP with our guide. Learn creational, structural, and behavioral patterns with clear, practical TypeScript examples to improve maintainability and design clarity.

Introduction

ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग में डिज़ाइन पैटर्न बार-बार आने वाली डिज़ाइन चुनौतियों का सिद्ध, पुन: उपयोग योग्य ब्लूप्रिंट होते हैं। ये सीधे कॉपी-पेस्ट करने के लिए कोड नहीं होते; ये अनुकूलनीय टेम्पलेट हैं जो आपकी क्लासेज़ और ऑब्जेक्ट्स को इस तरह संरचित करते हैं कि कोड को बनाना, बढ़ाना और टेस्ट करना आसान रहे। इस गाइड में हम creational, structural, और behavioral पैटर्न्स को व्यावहारिक TypeScript उदाहरणों के साथ समझाएंगे ताकि आप रियल-वर्ल्ड प्रॉब्लम्स के लिए सही पैटर्न चुन सकें।

What Are Design Patterns In Object-Oriented Programming

कभी बिना योजना के कुछ जटिल बनाने की कोशिश की है? डिज़ाइन पैटर्न के बिना कोडिंग एक उलझा हुआ कोडबेस दे सकती है जिसे स्केल और मेंटेन करना मुश्किल हो। पैटर्न परखे हुए समाधान हैं जो अच्छी डिजाइन प्रैक्टिसेज़ को कैप्चर करते हैं और टीमों के बीच साझा भाषा बनाते हैं।

एक शेफ़ की टोपी का स्केच जो सुनहरे अक्षर के आकार को एक खुले कुकबुक में गिरा रहा है।

The Shared Language of Developers

पैटर्न का सबसे बड़ा लाभ साझा शब्दावली है। “Factory” या “Singleton” कहें और अनुभवी डेवलपर्स तुरन्त इरादा समझ लेते हैं, जिससे डिज़ाइन डिस्कशन तेज़ और स्पष्ट होते हैं। Gang of Four ने 23 मूल पैटर्न सूचीबद्ध किए जो आज भी व्यापक रूप से इस्तेमाल होते हैं1। कुछ अकादमिक कामों ने भी पैटर्न्स के अमल में मापनीय लाभ दर्शाए हैं2

“A design pattern is not a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations.”

कोर OOP सिद्धांत—पॉलिमॉर्फिज़्म, इनहेरिटेंस और कंपोजिशन—पैटर्न को प्रभावी ढंग से लागू करने की नींव हैं। अगर आपको बेसिक OOP रिफ्रेशर चाहिए, तो इस लेख पर एक तुलना देखिए: Polymorphism vs Inheritance.

The Three Core Categories Of Design Patterns

Gang of Four ने पैटर्न्स को तीन श्रेणियों में बांटा: creational, structural, और behavioral। इन श्रेणियों को जानना समस्याओं के लिए तेज़ और उपयुक्त समाधान चुनने में मदद करता है।

creational, structural, and behavioural design patterns को सरल बॉक्स इलस्ट्रेशंस के साथ दर्शाता हुआ डायग्राम।

Overview of OOP Design Pattern Categories

Pattern CategoryCore PurposeCommon Examples
CreationalManage and abstract object creationFactory, Builder, Singleton, Prototype
StructuralCompose classes and objects into larger, flexible structuresAdapter, Decorator, Facade, Composite
BehavioralDefine how objects interact and communicateObserver, Strategy, Command, Iterator

Creational Patterns: The Construction Specialists

Creational पैटर्न्स यह नियंत्रित करते हैं कि ऑब्जेक्ट्स कैसे बनाए जाते हैं, ताकि क्लाइंट कोड concrete क्लासेज़ से tightly coupled न हो। वे instantiation लॉजिक को छिपाते हैं और implementations को बिना क्लाइंट बदलने के स्वैप करने की सुविधा देते हैं।

The Singleton Pattern: Ensuring One True Instance

Singleton सुनिश्चित करता है कि किसी क्लास का केवल एक ही उदाहरण हो और वह एक वैश्विक ऐक्सेस प्वाइंट प्रदान करे। यह डेटाबेस कनेक्शन या लॉगर जैसे साझा संसाधनों के लिए उपयोगी है, और इसके परीक्षण व डिपेंडेंसी मैनेजमेंट पर प्रभाव के बारे में सावधानी बरतनी चाहिए3

Example: a TypeScript Singleton for a database connection.

class DatabaseConnection {
  private static instance: DatabaseConnection;

  private constructor() {
    // A 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

The Factory Method: Letting Subclasses Decide What to Create

Factory Method एक ऑब्जेक्ट बनाने के लिए एक इंटरफ़ेस परिभाषित करता है, जबकि सबक्लासेस तय करती हैं कि किस concrete प्रोडक्ट को instantiate करना है। यह क्लाइंट कोड को concrete क्लासेज़ से decouple करता है और नए प्रोडक्ट जोड़ना सरल बनाता है।

Example: rendering OS-specific buttons in TypeScript.

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();

Structural Patterns: The Architectural Glue

Structural पैटर्न्स सिस्टम को बड़े, अनुकूलनीय हिस्सों में जोड़ने में मदद करते हैं। वे इंटरफेसों और क्लासेज़ के बीच रिश्तों को सरल करते हैं ताकि आप बिना बड़े बदलाव के सिस्टम का विस्तार कर सकें।

एक इलेक्ट्रिकल एडॉप्टर और रिंग्स के स्टैक का हैंड-ड्रॉन इलस्ट्रेशन जो OOP डिज़ाइन पैटर्न्स का प्रतिनिधित्व करता है।

The Adapter Pattern: Bridging Incompatible Interfaces

Adapter किसी असंगत इंटरफ़ेस को रैप करके उसे उस रूप में ढाल देता है जिसकी आपकी सिस्टम को उम्मीद होती है। यह लेगेसी कोड में invasive बदलाव करने से बचाता है।

Example: adapting a ModernLogger to an existing ILogger interface.

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.");

The Decorator Pattern: Adding Functionality Dynamically

Decorator runtime में ऑब्जेक्ट्स को रैप करके उन पर कार्यक्षमता जोड़ता है। यह subclassing की तुलना में अधिक लचीला है और Single Responsibility Principle का पालन करने में मदद करता है।

Example: composing a subscription with optional add-ons.

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());

Behavioral Patterns: Managing Interactions

Behavioral पैटर्न्स ऑब्जेक्ट्स के बीच इंटरैक्शन को व्यवस्थित करते हैं ताकि सिस्टम लचीला और मेंटेन करने योग्य रहे। वे कम्युनिकेशन पाथ्स को साफ़ करते हैं और जिम्मेदारियों को स्पष्ट करते हैं।

The Observer Pattern: Notifying Interested Parties

Observer एक one-to-many संबंध बनाता है: जब Subject बदलता है, Observers को सूचित किया जाता है। यह ईवेंट-ड्रिवन सिस्टम्स के लिए आदर्श है।

Example: a simple notification service.

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(`\nNotificationService: 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 एक loosely coupled डिज़ाइन पैदा करता है: Subjects को concrete Observers के बारे में पता होना जरूरी नहीं।

The Strategy Pattern: Encapsulating Algorithms

Strategy runtime पर एल्गोरिदम स्वैप करने देता है, जिससे बड़े conditional ब्लॉक्स से बचा जा सकता है और Open/Closed Principle का पालन आसान हो जाता है4

Example: payment strategies for a shopping cart.

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);

Common Design Pitfalls and Refactoring Strategies

किसी पैटर्न का चयन करना केवल आधी लड़ाई है। God Object जैसे एंटी-पैटर्न से बचें, जो जिम्मेदारियों को इकट्ठा कर लेता है और Single Responsibility Principle का उल्लंघन करता है। कोड स्मेल—लंबे मेथड्स, अत्यधिक डिपेंडेंसीज़, या विशाल क्लासेज़—पर ध्यान दें और अनुशासित रिफैक्टरिंग से उन्हें ठीक करें।

रिफैक्टरिंग का मतलब है बाहरी व्यवहार बदले बिना आंतरिक संरचना में सुधार करना; यही तरीका लेगेसी सिस्टम्स को सुरक्षित रूप से सुधारने का है।

Refactoring to the Strategy Pattern

बड़ा switch या लंबी if/else चेन एक क्लासिक स्मेल है। अलग व्यवहार को Strategy इंटरफ़ेस में निकालकर और concrete strategy क्लासेज़ बनाकर रिफैक्टर करें। इससे एक्स्टेंसिबिलिटी, टेस्टेबिलिटी और SOLID सिद्धांतों के पालन में सुधार होता है4

Answering Your Questions About OOP Design Patterns

How many design patterns should I learn?

पहले 5–7 महत्वपूर्ण पैटर्नों पर ध्यान दें: Singleton, Factory, Adapter, Decorator, Observer, और Strategy। हर पैटर्न किस समस्या को हल करता है यह समझना ज्यादा जरूरी है; एक बार वह समझ आ गया तो बाकी पैटर्न सीखना आसान हो जाता है।

When should I avoid using a design pattern?

ऐसे पैटर्न्स से बचें जो बिना किसी स्पष्ट समस्या के जटिलता जोड़ते हैं। किसी पैटर्न को तभी लागू करें जब वह वर्तमान समस्या का स्पष्ट समाधान दे—YAGNI का पालन करें।

Can I use design patterns with functional programming?

हाँ। कई पैटर्न्स फंक्शनल तकनीकों से अच्छी तरह मैप होते हैं—Strategy फ़ंक्शन पैरामीटर हो सकता है, और Decorator higher-order फ़ंक्शंस हो सकते हैं। कुंजी underlying सिद्धांत को लागू करना है बजाय सख्ती से OOP रूपों की नकल करने के।


At Clean Code Guy, we help teams build software that lasts by embedding foundational principles into their workflow. Discover how our code audits and AI-ready refactoring can get your team shipping with confidence at https://cleancodeguy.com.

1.
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
2.
W. G. Griswold et al., “A Formal Foundation for Design Pattern Abstraction and Reuse,” Proceedings of ECOOP ’93. https://cseweb.ucsd.edu/~wgg/CSE210/ecoop93-patterns.pdf
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,” explains Open/Closed and related design goals. https://8thlight.com/blog/uncle-bob/2012/08/13/the-s-o-l-i-d-principles.html
5.
Stack Overflow, Developer Survey 2023, shows TypeScript among the most-used languages in modern web development. https://insights.stackoverflow.com/survey/2023
← Back to blog
🙋🏻‍♂️

AI कोड लिखता है।
आप इसे टिकाऊ बनाते हैं।

AI त्वरण के युग में, क्लीन कोड केवल एक अच्छी प्रथा नहीं है — यह उन प्रणालियों के बीच का अंतर है जो स्केल होती हैं और कोडबेस जो अपने वजन के तहत ढह जाते हैं।