← Back to TypeScript Course | Chapter 16: Advanced Patterns | Lesson 6 of 7

Decorator Pattern (Design) की जानकारी

Decorator Pattern किसी object की original class बदलने के बजाय इसे wrap करके behavior जोड़ता है। कई decorators combine करके behavior dynamically बनाया जा सकता है।
Syntax
typescript
interface Component {
  operation(): ReturnType;
}

class Decorator implements Component {
  constructor(private wrapped: Component) {}
  operation(): ReturnType {
    return this.wrapped.operation(); // plus extra behavior
  }
}

Basic Decorator

एक decorator जिस component को wrap करता है उसी interface को implement करता है, original operation उस component को delegate करता है, और पहले या बाद में extra behavior जोड़ता है — caller यह नहीं बता सकता कि वह असली चीज़ के बजाय एक decorator से बात कर रहा है।

उदाहरण: Basic Decorator

typescript
interface Coffee {
  cost(): number;
}
class SimpleCoffee implements Coffee {
  cost() { return 5; }
}
class MilkDecorator implements Coffee {
  constructor(private coffee: Coffee) {}
  cost() { return this.coffee.cost() + 1; }
}
console.log(new MilkDecorator(new SimpleCoffee()).cost());

Decorators Stack करना

Decorators दूसरे decorators को wrap कर सकते हैं, तो कई independent behaviors — logging, caching, retries — को सिर्फ wrapping calls को nest करके एक object पर layer किया जा सकता है, हर layer सिर्फ उस एक को जानते हुए जिसे वह सीधे wrap करती है।

उदाहरण: Stacking Decorators

typescript
interface Coffee {
  cost(): number;
}
class SimpleCoffee implements Coffee {
  cost() { return 5; }
}
class MilkDecorator implements Coffee {
  constructor(private coffee: Coffee) {}
  cost() { return this.coffee.cost() + 1; }
}
class SugarDecorator implements Coffee {
  constructor(private coffee: Coffee) {}
  cost() { return this.coffee.cost() + 0.5; }
}
const order = new SugarDecorator(new MilkDecorator(new SimpleCoffee()));
console.log(order.cost());

Shared Interface

Original component और हर decorator को same interface follow करना चाहिए ताकि callers एक decorated object को exactly original की तरह treat कर सकें, call site पर किसी special-casing के बिना।

उदाहरण: Shared Interface

typescript
interface Notifier {
  send(message: string): void;
}
class EmailNotifier implements Notifier {
  send(message: string) { console.log("Email:", message); }
}
class SmsDecorator implements Notifier {
  constructor(private wrapped: Notifier) {}
  send(message: string) {
    this.wrapped.send(message);
    console.log("SMS:", message);
  }
}
new SmsDecorator(new EmailNotifier()).send("Hello");

Decorator बनाम Inheritance

Decorator runtime पर optional behavior जोड़ने के लिए composition उपयोग करता है, जबकि inheritance compile time पर एक fixed class hierarchy bake करता है — composition आपको एक rigid subclass tree से कहीं ज़्यादा flexibility से features mix and match करने देता है।

उदाहरण: Decorator vs Inheritance

typescript
interface Coffee { cost(): number; }
class SimpleCoffee implements Coffee { cost() { return 5; } }
// Inheritance would need a fixed subclass per combination (MilkCoffee, SugarCoffee, MilkSugarCoffee...)
// Decorator composes them at runtime instead:
class MilkDecorator implements Coffee {
  constructor(private coffee: Coffee) {}
  cost() { return this.coffee.cost() + 1; }
}
console.log(new MilkDecorator(new SimpleCoffee()).cost());

Decorator कब उपयोग करें

Decorator optional, composable features जैसे logging, caching, authorization, formatting, और notifications के लिए एक natural fit है — कुछ भी जो आप wrapped object के अपने code को touch किए बिना जोड़ना या हटाना चाहें।

उदाहरण: When to Use Decorator

typescript
interface Handler {
  handle(req: string): string;
}
class BaseHandler implements Handler {
  handle(req: string) { return `Handled: ${req}`; }
}
class LoggingDecorator implements Handler {
  constructor(private wrapped: Handler) {}
  handle(req: string) {
    console.log("Logging request:", req);
    return this.wrapped.handle(req);
  }
}
console.log(new LoggingDecorator(new BaseHandler()).handle("GET /"));
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. Same interface implement न करना, इसलिए decorated object को original की जगह उपयोग नहीं किया जा सकता।
  2. Wrapped object को delegate करना भूल जाना (this.coffee.cost()), इसलिए base behavior खो जाता है।
  3. इस pattern को @decorator syntax के साथ confuse करना, जो एक अलग feature है।
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.