🧩 Bridge × Strategy
✅ Intent of the Combination​
- The 
Bridgepattern separates the notification channel (e.g., Email / Slack) from the message formatting logic (e.g., Plain / HTML), allowing both to be extended independently. - The 
Strategypattern externalizes the message formatting behavior, enabling flexible combinations of notification channel × message style. 
This design consolidates common notification behavior within Notifier, while allowing flexible injection of both the communication method and message formatting strategy.
✅ When to Use​
- When you want to flexibly combine how a message is sent (Email, Slack, etc.) and how the message is structured (Plain text, HTML, Markdown, etc.).
 - When the system requires independent extensibility across multiple axes, such as output channels and content structure.
 - When designing systems with two or more independent concerns, such as UI vs. theme, or data vs. rendering method.
 
✅ UML Class Diagram​
✅ Code Example​
- TypeScript
 - PHP
 - Python
 
interface PaymentStrategy {
  pay(amount: number): void;
}
class CreditCardPayment implements PaymentStrategy {
  pay(amount: number): void {
    console.log(`[CreditCard] Paid ${amount}`);
  }
}
class PayPalPayment implements PaymentStrategy {
  pay(amount: number): void {
    console.log(`[PayPal] Paid ${amount}`);
  }
}
interface PaymentState {
  handle(amount: number): void;
  setStrategy(strategy: PaymentStrategy): void;
}
class ReadyState implements PaymentState {
  constructor(private strategy: PaymentStrategy) {}
  handle(amount: number): void {
    console.log("Ready to process payment");
    this.strategy.pay(amount);
  }
  setStrategy(strategy: PaymentStrategy): void {
    this.strategy = strategy;
  }
}
class DisabledState implements PaymentState {
  handle(amount: number): void {
    console.log("Payment is currently disabled");
  }
  setStrategy(strategy: PaymentStrategy): void {
    console.log("Cannot set strategy while disabled");
  }
}
class PaymentContext {
  constructor(private state: PaymentState) {}
  setState(state: PaymentState) {
    this.state = state;
  }
  setStrategy(strategy: PaymentStrategy) {
    this.state.setStrategy(strategy);
  }
  pay(amount: number) {
    this.state.handle(amount);
  }
}
// Usage
const context = new PaymentContext(new ReadyState(new CreditCardPayment()));
context.pay(100);
context.setStrategy(new PayPalPayment());
context.pay(200);
context.setState(new DisabledState());
context.pay(300);
<?php
interface PaymentStrategy {
  public function pay(int $amount): void;
}
class CreditCardPayment implements PaymentStrategy {
  public function pay(int $amount): void {
    echo "[CreditCard] Paid {$amount}\n";
  }
}
class PayPalPayment implements PaymentStrategy {
  public function pay(int $amount): void {
    echo "[PayPal] Paid {$amount}\n";
  }
}
interface PaymentState {
  public function handle(int $amount): void;
  public function setStrategy(PaymentStrategy $strategy): void;
}
class ReadyState implements PaymentState {
  private PaymentStrategy $strategy;
  public function __construct(PaymentStrategy $strategy) {
    $this->strategy = $strategy;
  }
  public function handle(int $amount): void {
    echo "Ready to process payment\n";
    $this->strategy->pay($amount);
  }
  public function setStrategy(PaymentStrategy $strategy): void {
    $this->strategy = $strategy;
  }
}
class DisabledState implements PaymentState {
  public function handle(int $amount): void {
    echo "Payment is currently disabled\n";
  }
  public function setStrategy(PaymentStrategy $strategy): void {
    echo "Cannot set strategy while disabled\n";
  }
}
class PaymentContext {
  private PaymentState $state;
  public function __construct(PaymentState $state) {
    $this->state = $state;
  }
  public function setState(PaymentState $state): void {
    $this->state = $state;
  }
  public function setStrategy(PaymentStrategy $strategy): void {
    $this->state->setStrategy($strategy);
  }
  public function pay(int $amount): void {
    $this->state->handle($amount);
  }
}
// Usage
$context = new PaymentContext(new ReadyState(new CreditCardPayment()));
$context->pay(100);
$context->setStrategy(new PayPalPayment());
$context->pay(200);
$context->setState(new DisabledState());
$context->pay(300);
from abc import ABC, abstractmethod
class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount: int) -> None:
        pass
class CreditCardPayment(PaymentStrategy):
    def pay(self, amount: int) -> None:
        print(f"[CreditCard] Paid {amount}")
class PayPalPayment(PaymentStrategy):
    def pay(self, amount: int) -> None:
        print(f"[PayPal] Paid {amount}")
class PaymentState(ABC):
    @abstractmethod
    def handle(self, amount: int) -> None:
        pass
    @abstractmethod
    def set_strategy(self, strategy: PaymentStrategy) -> None:
        pass
class ReadyState(PaymentState):
    def __init__(self, strategy: PaymentStrategy):
        self.strategy = strategy
    def handle(self, amount: int) -> None:
        print("Ready to process payment")
        self.strategy.pay(amount)
    def set_strategy(self, strategy: PaymentStrategy) -> None:
        self.strategy = strategy
class DisabledState(PaymentState):
    def handle(self, amount: int) -> None:
        print("Payment is currently disabled")
    def set_strategy(self, strategy: PaymentStrategy) -> None:
        print("Cannot set strategy while disabled")
class PaymentContext:
    def __init__(self, state: PaymentState):
        self.state = state
    def set_state(self, state: PaymentState) -> None:
        self.state = state
    def set_strategy(self, strategy: PaymentStrategy) -> None:
        self.state.set_strategy(strategy)
    def pay(self, amount: int) -> None:
        self.state.handle(amount)
# Usage
context = PaymentContext(ReadyState(CreditCardPayment()))
context.pay(100)
context.set_strategy(PayPalPayment())
context.pay(200)
context.set_state(DisabledState())
context.pay(300)
✅ Explanation​
Notifieris the abstraction that defines the notification flow. It holds a reference to aMessageStrategyto delegate message formatting (Strategy).EmailNotifierandSlackNotifierare concrete implementations of notification channels (implementors in theBridge).MessageStrategydefines how a message is built. It can be swapped dynamically (e.g.,PlainMessageStrategy,HtmlMessageStrategy).- The architecture enables independent extensibility of both how messages are sent and how they're formatted.
 
✅ Summary​
Bridgeseparates the concerns of how to send a message from how to build it, allowing independent extension.Strategyallows the message structure to be injected and changed dynamically.- This combination supports high flexibility and reusability, ideal for real-world systems where content and delivery vary independently.
 
This architecture is especially effective in real-world applications where multiple dimensions of extensibility are required, boosting maintainability and scalability.