Friday, March 13, 2026

Chain of Responsibility Design Pattern in PHP

Chain of Responsibility Design Pattern in PHP

🔗 What Is the Chain of Responsibility Pattern?

The Chain of Responsibility is a behavioral design pattern that lets you pass a request through a chain of handlers, where each handler decides either to process the request or pass it to the next handler in line.

Think of it like a helpdesk ticket system — your request moves up the support chain until someone has the authority or ability to resolve it.


🤔 Why Would I Use It in PHP?

  • When multiple classes could handle a request and you don’t want the sender to know which one will do it.
  • When you want to decouple the sender and receiver, making the system easier to maintain.
  • When you need a flexible structure for handling requests such as logging, validation, or middleware.

✅ Benefits of Using It in PHP

  • Enables clean separation of concerns by letting each handler focus on a specific task.
  • Makes code extensible, allowing handlers to be added, removed, or reordered easily.
  • Reduces tight coupling between components sending and processing requests.

UML / ORM

🌟 Chain of Responsibility — Participants (for PHP Students)

Handler

  • Defines the interface for handling requests.
  • Stores a reference to the next handler.
  • Forwards requests if it cannot handle them.

ConcreteHandler

  • Handles requests it is responsible for.
  • Decides whether to process or forward.
  • Passes unhandled requests to the successor.

Client

  • Sends requests to the first handler.
  • Does not know which handler processes the request.
  • Relies on the chain to handle requests.

PHP 8.2 Implementation

Handler.php

<?php
interface Handler
{
    public function setNext(Handler $handler): Handler;

    public function handle(string $request): ?string;
}

AbstractHandler.php

<?php
require_once 'Handler.php';

abstract class AbstractHandler implements Handler
{
    protected ?Handler $nextHandler = null;

    public function setNext(Handler $handler): Handler
    {
        $this->nextHandler = $handler;
        return $handler;
    }

    public function handle(string $request): ?string
    {
        if ($this->nextHandler) {
            return $this->nextHandler->handle($request);
        }

        return null;
    }
}

ConcreteHandlerA.php

<?php
require_once 'AbstractHandler.php';

class ConcreteHandlerA extends AbstractHandler
{
    public function handle(string $request): ?string
    {
        if ($request === 'A') {
            return "Handler A: I handled the request.";
        }

        return parent::handle($request);
    }
}

ConcreteHandlerB.php

<?php
require_once 'AbstractHandler.php';

class ConcreteHandlerB extends AbstractHandler
{
    public function handle(string $request): ?string
    {
        if ($request === 'B') {
            return "Handler B: I handled the request.";
        }

        return parent::handle($request);
    }
}

ConcreteHandlerC.php

<?php
require_once 'AbstractHandler.php';

class ConcreteHandlerC extends AbstractHandler
{
    public function handle(string $request): ?string
    {
        if ($request === 'C') {
            return "Handler C: I handled the request.";
        }

        return parent::handle($request);
    }
}

index.php

setNext($b)->setNext($c);

$requests = ['A','B','C','D'];

foreach ($requests as $request) {

    echo "Client: Who can handle '$request'?\n";

    $result = $a->handle($request);

    if ($result) {
        echo $result . "\n";
    } else {
        echo "No handler could handle the request.\n";
    }

    echo "----------------------------------------\n";
}

Expected Output

Client: Who can handle 'A'?
Handler A: I handled the request.
----------------------------------------
Client: Who can handle 'B'?
Handler B: I handled the request.
----------------------------------------
Client: Who can handle 'C'?
Handler C: I handled the request.
----------------------------------------
Client: Who can handle 'D'?
No handler could handle the request.

🧠 S.W.O.T. Analysis — Chain of Responsibility in PHP

Strengths

  1. Promotes flexibility by allowing dynamic addition or removal of handlers.
  2. Makes request processing modular and maintainable.
  3. Reduces large conditional logic by delegating responsibility.

Weaknesses

  1. Debugging may be harder when requests travel through the entire chain.
  2. Performance may degrade if the chain grows too long.
  3. Overuse may introduce unnecessary complexity.

Opportunities

  1. Helps build middleware-style request pipelines.
  2. Encourages modular responsibility delegation.
  3. Provides foundation for PSR-15 middleware frameworks.

Threats

  1. Misordered handlers may cause incorrect processing.
  2. Tightly coupled handlers defeat the pattern’s purpose.
  3. Poor exit conditions may result in unhandled requests.

Chain of Responsibility Design Pattern in Java

Chain of Responsibility Design Pattern in Java

The Chain of Responsibility Design Pattern enables decoupling between senders and receivers by allowing multiple objects to handle a request. The core idea is that a request is passed along a chain of potential handler objects. Each handler decides either to process the request or pass it to the next handler in the chain.

The sender of the request is unaware of which object in the chain will ultimately handle the request, ensuring that the sender and receiver operate independently.


Why Java Programmers Should Study the Chain of Responsibility Pattern

  1. Request Handling – Simplifies request processing by allowing multiple objects to handle a request dynamically.
  2. Decoupling Logic – Separates sender and receiver, improving maintainability and flexibility in evolving Java applications.
  3. Dynamic Responsibility – Enables defining or modifying the chain of responsibility at runtime.
  4. Error Handling – Useful for building robust error-handling chains where multiple modules can validate or log issues sequentially.
  5. Command Validation – Allows commands or user inputs to be validated through a series of validation handlers.
  6. Scalable Workflows – New handlers can be added or removed without modifying existing logic.
  7. Middleware Simulation – Simulates middleware behavior such as authentication, logging, and rate limiting in server-side Java applications.

Participants (for Java Students)

Handler

  • Defines the interface for handling requests.
  • Stores a reference to the next handler.
  • Forwards requests if it cannot handle them.

ConcreteHandler

  • Handles requests it is responsible for.
  • Decides whether to process or forward.
  • Passes unhandled requests to the successor.

Client

  • Sends requests to the first handler.
  • Does not know which handler processes the request.
  • Relies on the chain to handle requests.

Java Example — Sandwich Maker Chain

Imagine a chain of sandwich makers. Each maker specializes in adding one specific ingredient. If they don’t have that ingredient, they pass the sandwich down the line to the next expert.

SandwichMaker.java


public abstract class SandwichMaker {
    protected SandwichMaker nextMaker;

    public void setNextMaker(SandwichMaker nextMaker) {
        this.nextMaker = nextMaker;
    }

    public abstract void addIngredient(String ingredient);
}

BreadMaker.java


public class BreadMaker extends SandwichMaker {
    @Override
    public void addIngredient(String ingredient) {
        if (ingredient.equals("bread")) {
            System.out.println("BreadMaker: Toasting the bread. Nice and crispy!");
        } else {
            System.out.println("BreadMaker: I only deal with bread. Passing on...");
            if (nextMaker != null) nextMaker.addIngredient(ingredient);
        }
    }
}

LettuceAdder.java


public class LettuceAdder extends SandwichMaker {
    @Override
    public void addIngredient(String ingredient) {
        if (ingredient.equals("lettuce")) {
            System.out.println("LettuceAdder: Adding fresh green lettuce. Crunchy!");
        } else {
            System.out.println("LettuceAdder: Lettuce only, buddy. Next please...");
            if (nextMaker != null) nextMaker.addIngredient(ingredient);
        }
    }
}

CheeseSpreader.java


public class CheeseSpreader extends SandwichMaker {
    @Override
    public void addIngredient(String ingredient) {
        if (ingredient.equals("cheese")) {
            System.out.println("CheeseSpreader: Adding a thick slice of cheese. Yummy!");
        } else {
            System.out.println("CheeseSpreader: Cheese, please! Handing off...");
            if (nextMaker != null) nextMaker.addIngredient(ingredient);
        }
    }
}

Main.java


public class Main {
    public static void main(String[] args) {

        SandwichMaker breadMaker = new BreadMaker();
        SandwichMaker lettuceAdder = new LettuceAdder();
        SandwichMaker cheeseSpreader = new CheeseSpreader();

        breadMaker.setNextMaker(lettuceAdder);
        lettuceAdder.setNextMaker(cheeseSpreader);

        System.out.println("Making a sandwich with bread:\n");
        breadMaker.addIngredient("bread");

        System.out.println("\nMaking a sandwich with lettuce:\n");
        breadMaker.addIngredient("lettuce");

        System.out.println("\nMaking a sandwich with pickles:\n");
        breadMaker.addIngredient("pickles");
    }
}

Example Output


Making a sandwich with bread:

BreadMaker: Toasting the bread. Nice and crispy!

Making a sandwich with lettuce:

BreadMaker: I only deal with bread. Passing on...
LettuceAdder: Adding fresh green lettuce. Crunchy!

Making a sandwich with pickles:

BreadMaker: I only deal with bread. Passing on...
LettuceAdder: Lettuce only, buddy. Next please...
CheeseSpreader: Cheese, please! Handing off...

In this amusing sandwich shop, the BreadMaker only toasts bread, the LettuceAdder specializes in crunchy greens, and the CheeseSpreader focuses on that delicious cheese slice. If you ask for pickles though, the sandwich just travels through the chain with everyone passing it along, puzzled!


S.W.O.T. Analysis — Chain of Responsibility Pattern

Strengths

  1. Dynamic Workflow – Supports dynamic and flexible request-handling pipelines.
  2. Extensibility – Easily extended by adding new handlers.
  3. Decoupling – Clean separation between senders and receivers.

Weaknesses

  1. Execution Overhead – Long chains may reduce performance.
  2. Complex Debugging – Tracing requests through many handlers can be difficult.
  3. Order Dependency – Incorrect ordering of handlers may cause unexpected behavior.

Opportunities

  1. Middleware Pipelines – Useful for building middleware in Java frameworks.
  2. Event Handling – Effective for GUI and event-based systems.
  3. Authorization Chains – Ideal for multi-step authorization systems.

Threats

  1. Scalability Risks – Extremely long chains may impact scalability.
  2. Mismanagement – Poor chain management may introduce unexpected failures.
  3. Alternative Patterns – In some cases, patterns like State or Observer may be more appropriate.

Chain of Responsibility Design Pattern in JavaScript

Chain of Responsibility Design Pattern in JavaScript

🔗 What Is the Chain of Responsibility Design Pattern?

The Chain of Responsibility pattern is a behavioral pattern that lets you pass a request along a chain of handlers, where each handler decides whether to process it or pass it on.

Think of it like a customer service line: if the first person can’t help, they pass you to the next, until someone handles your issue.


🤔 Why Would I Use It?

  • When you want to avoid coupling the sender of a request to its receiver.
  • When you have multiple objects that might handle a request, but you don’t know which one ahead of time.
  • When you want to build flexible, dynamic chains for handling commands or events.

✅ Benefits of the Chain of Responsibility Pattern

  • Makes it easy to add or remove handlers without breaking other parts of the system.
  • Encourages loose coupling between senders and receivers of requests.
  • Supports flexible, reusable workflows where the order of handlers can change dynamically.

🧩 Summary

The Chain of Responsibility is about passing the buck until someone takes it:

“I’ll forward your call until the right person can answer it.”

It’s great for building flexible pipelines and event-handling systems.


UML / ORM Breakdown

1. Client

Starts the chain by making a request. Doesn’t worry about who will handle it — just gives it to the first link in the chain.

Example: “I need this done — whoever can handle it, please do.”

2. Handler

Sets the rule that every handler can either deal with the request or pass it along. Keeps a reference to the next handler in the chain.

Think of it as: “If I can’t do it, I’ll ask the next person.”

3. ConcreteHandler

Knows how to handle specific types of requests. If it recognizes the request, it takes care of it. If not, it forwards the request to the next handler.

In other words: “Not mine — passing it on.”


JavaScript Example

Below is a JavaScript example of the Chain of Responsibility pattern as described in the Design Patterns GoF book (pages 223–232), with the UML on page 223.

Participants in the GoF structure:

  • Handler — defines the interface to handle the request and set successor
  • ConcreteHandler — concrete implementation that either handles or forwards the request
  • Client — sends requests into the chain

This example includes:

  • Explanation of each class outside the code block
  • Fully commented code
  • Each class in its own .js module
  • A working index.js demo
  • GitHub-style README structure

🧩 Class-by-Class Explanation

🧩 Handler.js

Purpose

This is the abstract class (in JavaScript, a base class) that declares the handleRequest() method and holds the next handler in the chain. It defines the interface for chaining.

// Handler.js

// Handler is the base class for handling requests
class Handler {
    constructor() {
        this.successor = null; // next handler in the chain
    }

    // sets the next handler in the chain
    setSuccessor(successor) {
        this.successor = successor;
    }

    // defines the handling interface to override
    handleRequest(request) {
        throw new Error("handleRequest() must be implemented by subclasses.");
    }
}

module.exports = Handler;

🧩 ConcreteHandler1.js

Purpose

This concrete handler processes requests it understands; otherwise it forwards the request to its successor.

// ConcreteHandler1.js

const Handler = require('./Handler');

// ConcreteHandler1: handles requests in its range or forwards
class ConcreteHandler1 extends Handler {
    handleRequest(request) {
        // check if request is in range
        if (request >= 0 && request < 10) {
            console.log(`ConcreteHandler1 handled request ${request}`);
        } else if (this.successor) {
            console.log(`ConcreteHandler1 forwards ${request} to successor`);
            this.successor.handleRequest(request);
        }
    }
}

module.exports = ConcreteHandler1;

🧩 ConcreteHandler2.js

Purpose

This is another concrete handler in the chain. It handles a different range of requests or forwards them.

// ConcreteHandler2.js

const Handler = require('./Handler');

// ConcreteHandler2: handles requests in its range or forwards
class ConcreteHandler2 extends Handler {
    handleRequest(request) {
        // check if request is in range
        if (request >= 10 && request < 20) {
            console.log(`ConcreteHandler2 handled request ${request}`);
        } else if (this.successor) {
            console.log(`ConcreteHandler2 forwards ${request} to successor`);
            this.successor.handleRequest(request);
        }
    }
}

module.exports = ConcreteHandler2;

🧩 ConcreteHandler3.js

Purpose

A third handler in the chain, responsible for handling requests in its own range.

// ConcreteHandler3.js

const Handler = require('./Handler');

// ConcreteHandler3: handles requests in its range or ends the chain
class ConcreteHandler3 extends Handler {
    handleRequest(request) {
        // check if request is in range
        if (request >= 20 && request < 30) {
            console.log(`ConcreteHandler3 handled request ${request}`);
        } else {
            console.log(`ConcreteHandler3: no handler for ${request}`);
        }
    }
}

module.exports = ConcreteHandler3;

👤 Client.js

Purpose

The Client configures the chain of handlers and initiates the requests.

// Client.js

// Client builds the chain of handlers and sends requests
class Client {
    static run() {
        const ConcreteHandler1 = require('./ConcreteHandler1');
        const ConcreteHandler2 = require('./ConcreteHandler2');
        const ConcreteHandler3 = require('./ConcreteHandler3');

        const h1 = new ConcreteHandler1();
        const h2 = new ConcreteHandler2();
        const h3 = new ConcreteHandler3();

        // chain the handlers
        h1.setSuccessor(h2);
        h2.setSuccessor(h3);

        // issue requests
        const requests = [2, 5, 14, 22, 30];

        requests.forEach(request => {
            console.log(`Client: sending request ${request}`);
            h1.handleRequest(request);
        });
    }
}

module.exports = Client;

🚀 index.js

Purpose

This file starts the demonstration of the Chain of Responsibility pattern.

// index.js

const Client = require('./Client');

// start the Chain of Responsibility demo
Client.run();

✅ Expected Output

Client: sending request 2
ConcreteHandler1 handled request 2
Client: sending request 5
ConcreteHandler1 handled request 5
Client: sending request 14
ConcreteHandler1 forwards 14 to successor
ConcreteHandler2 handled request 14
Client: sending request 22
ConcreteHandler1 forwards 22 to successor
ConcreteHandler2 forwards 22 to successor
ConcreteHandler3 handled request 22
Client: sending request 30
ConcreteHandler1 forwards 30 to successor
ConcreteHandler2 forwards 30 to successor
ConcreteHandler3: no handler for 30

📚 References

  • Design Patterns: Elements of Reusable Object-Oriented Software (Gamma et al)
  • Chain of Responsibility Pattern, pages 223–232
  • UML page 223
  • Participants:
    • Handler
    • ConcreteHandler
    • Client

🧠 Teaching Notes

  • Explain how the chain is dynamic — the order or number of handlers can change at runtime.
  • Show how each handler either processes or forwards the request.
  • Discuss what happens when there is no handler for a request and the chain ends.

🧠 S.W.O.T. Analysis — Chain of Responsibility Pattern

✅ Strengths

  1. Simplifies client code by removing knowledge of who handles what request.
  2. Makes it easy to change the chain without affecting the client.
  3. Supports flexible and reusable request-handling pipelines.

❌ Weaknesses

  1. Can be hard to debug since requests may pass through many handlers.
  2. May result in requests not being handled if no handler takes responsibility.
  3. Adds complexity if the chain becomes too long or poorly organized.

🌱 Opportunities

  1. Helps juniors learn decoupled and modular request-processing techniques.
  2. Encourages designing systems that can grow or change handler order easily.
  3. Builds understanding for event systems, middleware, and interceptors.

⚠️ Threats

  1. Overuse may lead to tangled chains with unclear responsibilities.
  2. Improperly designed chains might skip critical processing steps.
  3. Performance may suffer if too many handlers are involved.

Chain of Responsibility Design Pattern in C#

Chain of Responsibility Design Pattern in C#

The Chain of Responsibility Design Pattern provides a mechanism to decouple senders from receivers by allowing more than one object to handle a request. In this pattern, a request is passed along a chain of potential handler objects until an object handles it or the chain's end is reached.

The key idea is that the sender broadcasts a request without knowing which object in the chain will serve the request, ensuring that the sender and receiver remain loosely coupled.


Why C# Programmers Should Study It

  1. Decoupling – Separates the sender of a request from the receiver, improving modular design.
  2. Flexible Request Handling – Handlers can be inserted, removed, or reordered easily.
  3. Maintainability – Each handler can be updated independently.
  4. Scalability – New handlers can be added without affecting existing code.
  5. Common in Middleware – Widely used in ASP.NET Core pipelines and other .NET middleware.
  6. Interception and Enhancements – Useful for logging, validation, and processing pipelines.
  7. Single Responsibility Principle – Each handler performs one task.
  8. Deepening OOP Mastery – Strengthens understanding of object-oriented design.
  9. Real-world Applicability – Useful for UI event processing and request pipelines.

Participants (for C# Students)

Handler

  • Declares the method for handling requests.
  • Stores a reference to the next Handler.
  • Forwards requests when unable to handle them.

ConcreteHandler

  • Handles requests within its responsibility range.
  • Decides whether to process or pass forward.
  • Sends unhandled requests to the successor.

Client

  • Sends request to the first handler.
  • Does not know which handler will process it.
  • Relies on the chain to manage the request.

C# Implementation

Handler Interface


public interface Handler
{
    Handler SetNext(Handler handler);
    object Handle(object request);
}

The default chaining behavior can be implemented in a base handler class. Returning the handler allows convenient chaining such as: mouse.SetNext(cat).SetNext(dog);

AbstractHandler.cs


abstract class AbstractHandler : Handler
{
    private Handler _nextHandler;

    public Handler SetNext(Handler handler)
    {
        this._nextHandler = handler;
        return handler;
    }
        
    public virtual object Handle(object request)
    {
        if (this._nextHandler != null)
        {
            return this._nextHandler.Handle(request);
        }
        else
        {
            return null;
        }
    }
}

MouseHandler.cs


class MouseHandler : AbstractHandler
{
    public override object Handle(object request)
    {
       if ((request as string) == "Cheese")
       {
           return $"Mouse: I'll eat the {request.ToString()}.\n";
       }
       else
       {
           return base.Handle(request);
       }
    }
}

CatHandler.cs


class CatHandler : AbstractHandler
{
    public override object Handle(object request)
    {
        if (request.ToString() == "Catnip")
        {
            return $"Cat: I love {request.ToString()}.\n";
        }
        else
        {
            return base.Handle(request);
        }
    }
}

DogHandler.cs


class DogHandler : AbstractHandler
{
    public override object Handle(object request)
    {
        if (request.ToString() == "Bone")
        {
            return $"Dog: Oh my!! I'll eat the {request.ToString()}.\n";
        }
        else
        {
            return base.Handle(request);
        }
    }
}

Client Code

The client usually interacts with a single handler and is unaware that a chain exists.


class Client
{
    public static void ClientCode(AbstractHandler handler)
    {
        foreach (var food in new List<string> { "Bone", "Catnip", "Cheese" })
        {
            Console.WriteLine($"Client: Who wants a {food}?");
            var result = handler.Handle(food);

            if (result != null)
            {
                Console.Write($"   {result}");
            }
            else
            {
                Console.WriteLine($"   {food} was left untouched.");
            }
        }
    }
}

Program.cs


class Program
{
    static void Main(string[] args)
    {
        var mouse = new MouseHandler();
        var cat = new CatHandler();
        var dog = new DogHandler();

        mouse.SetNext(cat).SetNext(dog);

        Console.WriteLine("Chain: Dog > Cat > Mouse\n");
        Client.ClientCode(mouse);
        Console.WriteLine();

        Console.WriteLine("Subchain: Dog > Cat\n");
        Client.ClientCode(cat);
    }
}

Expected Output


Chain: Dog > Cat > Mouse
Client: Who wants a Bone?
   Dog: Oh my!! I'll eat the Bone.
Client: Who wants a Catnip?
   Cat: I love Catnip.
Client: Who wants a Cheese?
   Mouse: I'll eat the Cheese.

Subchain: Dog > Cat
Client: Who wants a Bone?
   Dog: Oh my!! I'll eat the Bone.
Client: Who wants a Catnip?
   Cat: I love Catnip.
Client: Who wants a Cheese?
   Cheese was left untouched.

Or shall I say… the cheese stands alone.


S.W.O.T. Analysis

Strengths

  • Encapsulates request processing into independent handlers.
  • Promotes separation of concerns.
  • Allows scalable request pipelines.
  • Maintains consistency in processing behavior.

Weaknesses

  • Introduces additional classes and interfaces.
  • Can increase complexity in small applications.
  • Extending handler types may require refactoring.

Opportunities

  • Works well with modern C# features like dependency injection.
  • Ideal for middleware pipelines in ASP.NET Core.
  • Highly applicable in enterprise software systems.

Threats

  • Risk of overengineering when unnecessary.
  • Potential performance overhead from multiple handlers.
  • Misuse by inexperienced developers can complicate architecture.

Thursday, March 05, 2026

Abstract Factory Design Pattern

The Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. (For Java developers)

5 Reasons to Study the Abstract Factory Pattern (for Java Developers)

1. Modularity Encourages code that’s easier to maintain by abstracting object creation for UI themes or database drivers.
2. Scalability Enables building complex systems — like GUI frameworks — where object families must evolve without breaking code.
3. Flexibility Supports switching between different product variants with minimal code changes.
4. Consistency Helps ensure that Java components from the same family are used together, avoiding incompatibility bugs.
5. Testability Facilitates mocking dependencies in unit tests by abstracting object creation behind factory interfaces.


🧩 ORM / UML Structure

The Abstract Factory pattern defines a set of product interfaces and a factory interface that creates the products. Concrete factories implement the factory interface to produce specific product variants. Clients depend only on abstract interfaces, allowing products and families to vary independently. Each concrete factory produces related products that share consistent behavior.


🌟 Abstract Factory — Participants (for Java Students)

AbstractFactory

  • Declares creation methods for each type of product.
  • Defines how families of products should be created without specifying concrete classes.
  • Enables interchangeability of entire product families.

ConcreteFactory

  • Implements the product creation methods defined in the AbstractFactory.
  • Returns concrete product instances belonging to a specific family (e.g., Italian or Indian meals).
  • Ensures that related products are consistent with a family’s theme.

AbstractProduct

  • Defines the interface for a type of product.
  • Ensures that all products in a family share common behavior.
  • Makes it possible for client code to use products polymorphically.

ConcreteProduct

  • Implements the AbstractProduct interface.
  • Provides specific product behavior (e.g., ItalianMainCourse or IndianDessert).
  • Works with other products from the same family.

Client

  • Uses only abstract interfaces — AbstractFactory and AbstractProduct.
  • Does not depend on concrete product classes.
  • Remains unaffected by changes to product families.

💻 Java Code Example

This example demonstrates a meal creation system using the Abstract Factory pattern. Two product types — main courses and desserts — are created by factories representing different meal types (Italian and Indian). :contentReference[oaicite:1]{index=1}

File: MainCourse.java


// MainCourse.java
public interface MainCourse {
    void serve();
}

File: Dessert.java


// Dessert.java
public interface Dessert {
    void serve();
}

File: ItalianMainCourse.java


// ItalianMainCourse.java
public class ItalianMainCourse implements MainCourse {
    @Override
    public void serve() {
        System.out.println("Serving an Italian pasta dish.");
    }
}

File: IndianMainCourse.java


// IndianMainCourse.java
public class IndianMainCourse implements MainCourse {
    @Override
    public void serve() {
        System.out.println("Serving an Indian curry dish.");
    }
}

File: ItalianDessert.java


// ItalianDessert.java
public class ItalianDessert implements Dessert {
    @Override
    public void serve() {
        System.out.println("Serving an Italian tiramisu dessert.");
    }
}

File: IndianDessert.java


// IndianDessert.java
public class IndianDessert implements Dessert {
    @Override
    public void serve() {
        System.out.println("Serving an Indian gulab jamun dessert.");
    }
}

File: MealFactory.java


// MealFactory.java
public interface MealFactory {
    MainCourse createMainCourse();
    Dessert createDessert();
}

File: ItalianMealFactory.java


// ItalianMealFactory.java
public class ItalianMealFactory implements MealFactory {
    @Override
    public MainCourse createMainCourse() {
        return new ItalianMainCourse();
    }
    @Override
    public Dessert createDessert() {
        return new ItalianDessert();
    }
}

File: IndianMealFactory.java


// IndianMealFactory.java
public class IndianMealFactory implements MealFactory {
    @Override
    public MainCourse createMainCourse() {
        return new IndianMainCourse();
    }
    @Override
    public Dessert createDessert() {
        return new IndianDessert();
    }
}

File: Main.java


// Main.java
public class Main {
    public static void main(String[] args) {
        MealFactory italianFactory = new ItalianMealFactory();
        MealFactory indianFactory = new IndianMealFactory();

        MainCourse italianMainCourse = italianFactory.createMainCourse();
        Dessert italianDessert = italianFactory.createDessert();

        MainCourse indianMainCourse = indianFactory.createMainCourse();
        Dessert indianDessert = indianFactory.createDessert();

        italianMainCourse.serve();
        italianDessert.serve();
        indianMainCourse.serve();
        indianDessert.serve();
    }
}

🧠 S.W.O.T. Analysis

✅ Strengths

  • Promotes clean separation between interface and implementation layers.
  • Simplifies the addition of new product families.
  • Reduces code duplication across product variants.

⚠️ Weaknesses

  • Increases complexity with multiple classes and interfaces.
  • Can lead to over-engineering in simple applications.
  • May obscure concrete object behavior from developers.

🚀 Opportunities

  • Ideal for plug-in architectures and enterprise-level system design.
  • Enables cross-platform UI development using consistent abstractions.
  • Supports Java applications needing runtime product switching.

⚡ Threats

  • Misuse can make debugging object creation chains difficult.
  • May hinder performance if used inappropriately in resource-constrained apps.
  • Could confuse team members unfamiliar with design patterns.

Tuesday, February 17, 2026

C++ Chain Of Responsibility Design Pattern with S.W.O.T. Analysis

Chain Of Responsibility Design Pattern

The Chain of Responsibility Design Pattern is a behavioral pattern that allows a request to pass through a chain of handlers until one of them handles it.

Instead of having a single object responsible for processing a request, multiple objects are given a chance to handle it. The request moves along the chain until it reaches an object capable of processing it.

This design pattern promotes loose coupling between the sender and receiver. The sender does not need to know which object will handle the request — only that the request will be handled somewhere in the chain.

By decoupling request senders from receivers, we create flexible, maintainable, and efficient design.


🧩 ORM / UML Structure

The UML structure of Chain of Responsibility contains three primary participants:

  • Handler (Interface / Abstract Class)
  • ConcreteHandler
  • Client

The key relationship is:

Client → Handler → ConcreteHandler → ConcreteHandler → ...

Each handler contains:

  • A reference to the next handler
  • A method to handle the request
  • Logic to either process or forward the request

The power of this pattern lies in the dynamic linking of handlers at runtime.


🌟 Chain of Responsibility — Participants (for C++ Students)

Handler

  • Defines the interface for handling requests.
  • Stores a reference to the next Handler.
  • Forwards requests if it cannot handle them.

ConcreteHandler

  • Handles requests it is responsible for.
  • Decides whether to process or forward.
  • Passes unhandled requests to successor.

Client

  • Sends requests to the first Handler.
  • Does not know which Handler processes it.
  • Relies on the chain for handling.

💻 C++ Code Example

Below is the example formatted cleanly for blog presentation.

Handler Interface

#ifndef HANDLER_H
#define HANDLER_H

#include <string>

class Handler {
protected:
    Handler* next;

public:
    Handler() : next(nullptr) {}

    virtual ~Handler() {}

    void setNext(Handler* handler) {
        next = handler;
    }

    virtual void handleRequest(const std::string& request) = 0;
};

#endif

ConcreteHandlerA

#ifndef CONCRETEHANDLERA_H
#define CONCRETEHANDLERA_H

#include "Handler.h"
#include <iostream>

class ConcreteHandlerA : public Handler {
public:
    void handleRequest(const std::string& request) override {
        if (request == "A") {
            std::cout << "ConcreteHandlerA handled request A\n";
        } else if (next) {
            next->handleRequest(request);
        }
    }
};

#endif

ConcreteHandlerB

#ifndef CONCRETEHANDLERB_H
#define CONCRETEHANDLERB_H

#include "Handler.h"
#include <iostream>

class ConcreteHandlerB : public Handler {
public:
    void handleRequest(const std::string& request) override {
        if (request == "B") {
            std::cout << "ConcreteHandlerB handled request B\n";
        } else if (next) {
            next->handleRequest(request);
        }
    }
};

#endif

main.cpp (Client)

#include "ConcreteHandlerA.h"
#include "ConcreteHandlerB.h"

int main() {
    ConcreteHandlerA handlerA;
    ConcreteHandlerB handlerB;

    handlerA.setNext(&handlerB);

    handlerA.handleRequest("A");
    handlerA.handleRequest("B");
    handlerA.handleRequest("C");

    return 0;
}

🧠 S.W.O.T. Analysis

✅ Strengths

  • Promotes loose coupling between sender and receiver.
  • Flexible and dynamic chain construction.
  • Respects Open/Closed Principle.

⚠️ Weaknesses

  • Can be harder to debug.
  • No guarantee a request will be handled.
  • Chain configuration must be done carefully.

🚀 Opportunities

  • Ideal for middleware systems.
  • Excellent for event processing pipelines.
  • Common in logging, GUI event handling, and request processing systems.

⚡ Threats

  • Long chains may reduce performance.
  • Improper chain setup can cause silent failures.
  • Overuse may complicate simple workflows.

Tuesday, February 10, 2026

PHP Structural Pattern the Adapter with code sample and UML

Adapter Design Pattern

The Adapter Design Pattern, categorized under Structural design patterns, acts as a bridge between two incompatible interfaces, enabling them to work together.

The pattern introduces an intermediary interface (the Adapter) that converts one interface into another, allowing classes with incompatible interfaces to collaborate seamlessly.


Why Should PHP Programmers Study the Adapter Design Pattern?

  1. Legacy System Integration:
    Enables modern PHP systems to work with older codebases without large rewrites.
  2. Third-party Tool Compatibility:
    Smooths integration when external libraries expose incompatible interfaces.
  3. Improved Code Reusability:
    Adapts existing components instead of rewriting working logic.
  4. Better Modularity:
    Keeps interface translation separate from business logic.
  5. Flexible System Evolution:
    Supports adding new functionality without disturbing existing architecture.
  6. Open/Closed Principle:
    Extends behavior without modifying existing classes.
  7. Simplified Interfaces:
    Wraps complex APIs into developer-friendly interfaces.
  8. Versatile Adaptation:
    Multiple adapters can support multiple integration scenarios.

Adapter — UML

Target

  • Defines the interface the Client expects
  • Represents standard system behavior
  • Used directly by the Client

Client

  • Works through the Target interface
  • Is unaware of the Adaptee
  • Relies on Adapter for compatibility

Adaptee

  • Has an incompatible interface
  • Contains useful existing functionality
  • Cannot be easily modified

Adapter

  • Implements the Target interface
  • Translates Client requests
  • Connects incompatible interfaces

Target.php

interface Target
{
    public function request(): string;
}

Adaptee.php

class Adaptee
{
    public function specificRequest(): string
    {
        return "Specific request from Adaptee.";
    }
}

Adapter.php

class Adapter implements Target
{
    private $adaptee;

    public function __construct(Adaptee $adaptee)
    {
        $this->adaptee = $adaptee;
    }

    public function request(): string
    {
        return "Adapter: " . $this->adaptee->specificRequest();
    }
}

index.php

require_once 'Target.php';
require_once 'Adaptee.php';
require_once 'Adapter.php';

function clientCode(Target $target)
{
    echo $target->request();
}

echo "Client code with Adaptee:<br/>";
$adaptee = new Adaptee();
echo $adaptee->specificRequest();
echo "<br/><br/>";

echo "Client code with Adapter:<br/>";
$adapter = new Adapter($adaptee);
clientCode($adapter);

Key Idea

The Adapter pattern wraps an existing class and translates method calls from the Target interface into calls understood by the Adaptee, allowing incompatible interfaces to work together without modification.


S.W.O.T. Analysis — Adapter Pattern (PHP)

Strengths

  • Enables seamless interface compatibility
  • Promotes reuse of legacy and third-party code
  • Decouples client logic from implementation

Weaknesses

  • Adds abstraction layers
  • May introduce slight performance overhead
  • Often temporary when legacy systems are replaced

Opportunities

  • Legacy modernization
  • Third-party API standardization
  • Cross-language integration

Threats

  • Bypassing adapters leads to inconsistency
  • Overuse can clutter architecture
  • Direct refactoring may be a better long-term solution

Chain of Responsibility Design Pattern in PHP

Chain of Responsibility Design Pattern in PHP 🔗 What Is the Chain of Responsibility Pattern? The Chain of Responsibility is a behavio...