Behavioral Design Patterns
In plain words
It is concerned with assignment of responsibilities between the objects. What makes them different from structural patterns is they don't just specify the structure but also outline the patterns for message passing/communication between them. Or in other words, they assist in answering "How to run a behavior in software component"
Wikipedia says
In software engineering, behavioral design patterns are design patterns that identify common communication patterns between objects and realize these patterns. By doing so, these patterns increase flexibility in carrying out this communication.
Chain of Responsibility
Real world example
For example, you have three payment methods (
A
,B
andC
) setup in your account; each having a different amount in it.A
has 100 USD,B
has 300 USD andC
having 1000 USD and the preference for payments is chosen asA
thenB
thenC
. You try to purchase something that is worth 210 USD. Using Chain of Responsibility, first of all accountA
will be checked if it can make the purchase, if yes purchase will be made and the chain will be broken. If not, request will move forward to accountB
checking for amount if yes chain will be broken otherwise the request will keep forwarding till it finds the suitable handler. HereA
,B
andC
are links of the chain and the whole phenomenon is Chain of Responsibility.
In plain words
It helps building a chain of objects. Request enters from one end and keeps going from object to object till it finds the suitable handler.
Wikipedia says
In object-oriented design, the chain-of-responsibility pattern is a design pattern consisting of a source of command objects and a series of processing objects. Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain.
Programmatic Example
Translating our account example above. First of all we have a base account having the logic for chaining the accounts together and some accounts
- abstract class Account
- {
- protected $successor;
- protected $balance;
- public function setNext(Account $account)
- {
- $this->successor = $account;
- }
- public function pay(float $amountToPay)
- {
- if ($this->canPay($amountToPay)) {
- echo sprintf('Paid %s using %s' . PHP_EOL, $amountToPay, get_called_class());
- } elseif ($this->successor) {
- echo sprintf('Cannot pay using %s. Proceeding ..' . PHP_EOL, get_called_class());
- $this->successor->pay($amountToPay);
- } else {
- throw new Exception('None of the accounts have enough balance');
- }
- }
- public function canPay($amount): bool
- {
- return $this->balance >= $amount;
- }
- }
- class Bank extends Account
- {
- protected $balance;
- public function __construct(float $balance)
- {
- $this->balance = $balance;
- }
- }
- class Paypal extends Account
- {
- protected $balance;
- public function __construct(float $balance)
- {
- $this->balance = $balance;
- }
- }
- class Bitcoin extends Account
- {
- protected $balance;
- public function __construct(float $balance)
- {
- $this->balance = $balance;
- }
- }
Now let's prepare the chain using the links defined above (i.e. Bank, Paypal, Bitcoin)
- // Let's prepare a chain like below
- // $bank->$paypal->$bitcoin
- //
- // First priority bank
- // If bank can't pay then paypal
- // If paypal can't pay then bit coin
- $bank = new Bank(100); // Bank with balance 100
- $paypal = new Paypal(200); // Paypal with balance 200
- $bitcoin = new Bitcoin(300); // Bitcoin with balance 300
- $bank->setNext($paypal);
- $paypal->setNext($bitcoin);
- // Let's try to pay using the first priority i.e. bank
- $bank->pay(259);
- // Output will be
- // ==============
- // Cannot pay using bank. Proceeding ..
- // Cannot pay using paypal. Proceeding ..:
- // Paid 259 using Bitcoin!
Command
Real world example
A generic example would be you ordering food at a restaurant. You (i.e.
Client
) ask the waiter (i.e.Invoker
) to bring some food (i.e.Command
) and waiter simply forwards the request to Chef (i.e.Receiver
) who has the knowledge of what and how to cook.Another example would be you (i.e.Client
) switching on (i.e.Command
) the television (i.e.Receiver
) using a remote control (Invoker
).
In plain words
Allows you to encapsulate actions in objects. The key idea behind this pattern is to provide the means to decouple client from receiver.
Wikipedia says
In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time. This information includes the method name, the object that owns the method and values for the method parameters.
Programmatic Example
First of all we have the receiver that has the implementation of every action that could be performed
- // Receiver
- class Bulb
- {
- public function turnOn()
- {
- echo "Bulb has been lit";
- }
- public function turnOff()
- {
- echo "Darkness!";
- }
- }
then we have an interface that each of the commands are going to implement and then we have a set of commands
- interface Command
- {
- public function execute();
- public function undo();
- public function redo();
- }
- // Command
- class TurnOn implements Command
- {
- protected $bulb;
- public function __construct(Bulb $bulb)
- {
- $this->bulb = $bulb;
- }
- public function execute()
- {
- $this->bulb->turnOn();
- }
- public function undo()
- {
- $this->bulb->turnOff();
- }
- public function redo()
- {
- $this->execute();
- }
- }
- class TurnOff implements Command
- {
- protected $bulb;
- public function __construct(Bulb $bulb)
- {
- $this->bulb = $bulb;
- }
- public function execute()
- {
- $this->bulb->turnOff();
- }
- public function undo()
- {
- $this->bulb->turnOn();
- }
- public function redo()
- {
- $this->execute();
- }
- }
Then we have an Invoker
with whom the client will interact to process any commands
- // Invoker
- class RemoteControl
- {
- public function submit(Command $command)
- {
- $command->execute();
- }
- }
Finally let's see how we can use it in our client
- $bulb = new Bulb();
- $turnOn = new TurnOn($bulb);
- $turnOff = new TurnOff($bulb);
- $remote = new RemoteControl();
- $remote->submit($turnOn); // Bulb has been lit!
- $remote->submit($turnOff); // Darkness!
Command pattern can also be used to implement a transaction based system. Where you keep maintaining the history of commands as soon as you execute them. If the final command is successfully executed, all good otherwise just iterate through the history and keep executing the undo
on all the executed commands.
➿ Iterator
Real world example
An old radio set will be a good example of iterator, where user could start at some channel and then use next or previous buttons to go through the respective channels. Or take an example of MP3 player or a TV set where you could press the next and previous buttons to go through the consecutive channels or in other words they all provide an interface to iterate through the respective channels, songs or radio stations.
In plain words
It presents a way to access the elements of an object without exposing the underlying presentation.
Wikipedia says
In object-oriented programming, the iterator pattern is a design pattern in which an iterator is used to traverse a container and access the container's elements. The iterator pattern decouples algorithms from containers; in some cases, algorithms are necessarily container-specific and thus cannot be decoupled.
Programmatic example
In PHP it is quite easy to implement using SPL (Standard PHP Library). Translating our radio stations example from above. First of all we have RadioStation
- class RadioStation
- {
- protected $frequency;
- public function __construct(float $frequency)
- {
- $this->frequency = $frequency;
- }
- public function getFrequency(): float
- {
- return $this->frequency;
- }
- }
Then we have our iterator
- use Countable;
- use Iterator;
- class StationList implements Countable, Iterator
- {
- /** @var RadioStation[] $stations */
- protected $stations = [];
- /** @var int $counter */
- protected $counter;
- public function addStation(RadioStation $station)
- {
- $this->stations[] = $station;
- }
- public function removeStation(RadioStation $toRemove)
- {
- $toRemoveFrequency = $toRemove->getFrequency();
- $this->stations = array_filter($this->stations, function (RadioStation $station) use ($toRemoveFrequency) {
- return $station->getFrequency() !== $toRemoveFrequency;
- });
- }
- public function count(): int
- {
- return count($this->stations);
- }
- public function current(): RadioStation
- {
- return $this->stations[$this->counter];
- }
- public function key()
- {
- return $this->counter;
- }
- public function next()
- {
- $this->counter++;
- }
- public function rewind()
- {
- $this->counter = 0;
- }
- public function valid(): bool
- {
- return isset($this->stations[$this->counter]);
- }
- }
And then it can be used as
- $stationList = new StationList();
- $stationList->addStation(new RadioStation(89));
- $stationList->addStation(new RadioStation(101));
- $stationList->addStation(new RadioStation(102));
- $stationList->addStation(new RadioStation(103.2));
- foreach($stationList as $station) {
- echo $station->getFrequency() . PHP_EOL;
- }
- $stationList->removeStation(new RadioStation(89)); // Will remove station 89