Chelistico

It's a tech blog!

Behavioral Design Patterns in System Development

By Marcelo Vieyra, October 31st 2023 | 3 mins, 505 words

Behavioral design patterns address the ways in which objects and classes interact and communicate. They deal with the responsibilities and collaboration of objects. Some of the most commonly used behavioral patterns include:

1. Observer Pattern

The Observer pattern defines a one-to-many dependency between objects. When one object (the subject) changes state, all its dependents (observers) are notified and updated automatically. Here's an example in PHP:

interface Observer {
    public function update($message);
}

class ConcreteObserver implements Observer {
    public function update($message) {
        echo "Received message: " . $message . "\n";
    }
}

class Subject {
    private $observers = [];

    public function attach(Observer $observer) {
        $this->observers[] = $observer;
    }

    public function notify($message) {
        foreach ($this->observers as $observer) {
            $observer->update($message);
        }
    }
}

2. Strategy Pattern

The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. It allows the client to choose the appropriate algorithm at runtime. Here's an example in PHP:

interface Strategy {
    public function execute($data);
}

class ConcreteStrategyA implements Strategy {
    public function execute($data) {
        return "Using Strategy A with data: " . $data;
    }
}

class Context {
    private $strategy;

    public function setStrategy(Strategy $strategy) {
        $this->strategy = $strategy;
    }

    public function executeStrategy($data) {
        return $this->strategy->execute($data);
    }
}

3. Chain of Responsibility Pattern

The Chain of Responsibility pattern allows you to pass requests along a chain of handlers. Each handler decides either to process the request or pass it to the next handler in the chain. Here's an example in PHP:

abstract class Handler {
    protected $successor;

    public function setSuccessor(Handler $handler) {
        $this->successor = $handler;
    }

    public abstract function handleRequest($request);
}

class ConcreteHandlerA extends Handler {
    public function handleRequest($request) {
        if ($request == "A") {
            return "Handled by Handler A";
        } elseif ($this->successor != null) {
            return $this->successor->handleRequest($request);
        }
        return "Request not handled";
    }
}

4. Command Pattern

The Command pattern encapsulates a request as an object, thereby allowing for parameterization of clients with queuing, requests, and operations. It also allows for the support of undoable operations. Here's an example in PHP:

interface Command {
    public function execute();
}

class ConcreteCommand implements Command {
    private $receiver;

    public function __construct(Receiver $receiver) {
        $this->receiver = $receiver;
    }

    public function execute() {
        return $this->receiver->action();
    }
}

class Receiver {
    public function action() {
        return "Receiver: executing action";
    }
}

class Invoker {
    private $command;

    public function setCommand(Command $command) {
        $this->command = $command;
    }

    public function executeCommand() {
        return $this->command->execute();
    }
}

5. Interpreter Pattern

The Interpreter pattern defines a grammar for a language and provides an interpreter to interpret sentences in the language. It's used to interpret or evaluate the expressions. Here's an example in PHP:

interface Expression {
    public function interpret($context);
}

class TerminalExpression implements Expression {
    public function interpret($context) {
        return $context->contains($this);
    }
}

class NonTerminalExpression implements Expression {
    private $expression;

    public function __construct(Expression $expression) {
        $this->expression = $expression;
    }

    public function interpret($context) {
        return !$this->expression->interpret($context);
    }
}

class Context {
    private $data = [];

    public function contains(Expression $expression) {
        // Check if expression exists in data
    }
}

Conclusion

Behavioral design patterns are crucial for system development, enabling developers to define the interactions between objects effectively. These patterns enhance the flexibility and maintainability of software systems by promoting clear communication and collaboration between different parts of the system.