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 and C) setup in your account; each having a different amount in it. A has 100 USD, B has 300 USD and C having 1000 USD and the preference for payments is chosen as A then B then C. You try to purchase something that is worth 210 USD. Using Chain of Responsibility, first of all account A 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 account B checking for amount if yes chain will be broken otherwise the request will keep forwarding till it finds the suitable handler. Here A, B and C 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

  1. abstract class Account
  2. {
  3. protected $successor;
  4. protected $balance;
  5.  
  6. public function setNext(Account $account)
  7. {
  8. $this->successor = $account;
  9. }
  10.  
  11. public function pay(float $amountToPay)
  12. {
  13. if ($this->canPay($amountToPay)) {
  14. echo sprintf('Paid %s using %s' . PHP_EOL, $amountToPay, get_called_class());
  15. } elseif ($this->successor) {
  16. echo sprintf('Cannot pay using %s. Proceeding ..' . PHP_EOL, get_called_class());
  17. $this->successor->pay($amountToPay);
  18. } else {
  19. throw new Exception('None of the accounts have enough balance');
  20. }
  21. }
  22.  
  23. public function canPay($amount): bool
  24. {
  25. return $this->balance >= $amount;
  26. }
  27. }
  28.  
  29. class Bank extends Account
  30. {
  31. protected $balance;
  32.  
  33. public function __construct(float $balance)
  34. {
  35. $this->balance = $balance;
  36. }
  37. }
  38.  
  39. class Paypal extends Account
  40. {
  41. protected $balance;
  42.  
  43. public function __construct(float $balance)
  44. {
  45. $this->balance = $balance;
  46. }
  47. }
  48.  
  49. class Bitcoin extends Account
  50. {
  51. protected $balance;
  52.  
  53. public function __construct(float $balance)
  54. {
  55. $this->balance = $balance;
  56. }
  57. }

Now let's prepare the chain using the links defined above (i.e. Bank, Paypal, Bitcoin)

  1. // Let's prepare a chain like below
  2. // $bank->$paypal->$bitcoin
  3. //
  4. // First priority bank
  5. // If bank can't pay then paypal
  6. // If paypal can't pay then bit coin
  7.  
  8. $bank = new Bank(100); // Bank with balance 100
  9. $paypal = new Paypal(200); // Paypal with balance 200
  10. $bitcoin = new Bitcoin(300); // Bitcoin with balance 300
  11.  
  12. $bank->setNext($paypal);
  13. $paypal->setNext($bitcoin);
  14.  
  15. // Let's try to pay using the first priority i.e. bank
  16. $bank->pay(259);
  17.  
  18. // Output will be
  19. // ==============
  20. // Cannot pay using bank. Proceeding ..
  21. // Cannot pay using paypal. Proceeding ..:
  22. // 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

  1. // Receiver
  2. class Bulb
  3. {
  4. public function turnOn()
  5. {
  6. echo "Bulb has been lit";
  7. }
  8.  
  9. public function turnOff()
  10. {
  11. echo "Darkness!";
  12. }
  13. }

then we have an interface that each of the commands are going to implement and then we have a set of commands

  1. interface Command
  2. {
  3. public function execute();
  4. public function undo();
  5. public function redo();
  6. }
  7.  
  8. // Command
  9. class TurnOn implements Command
  10. {
  11. protected $bulb;
  12.  
  13. public function __construct(Bulb $bulb)
  14. {
  15. $this->bulb = $bulb;
  16. }
  17.  
  18. public function execute()
  19. {
  20. $this->bulb->turnOn();
  21. }
  22.  
  23. public function undo()
  24. {
  25. $this->bulb->turnOff();
  26. }
  27.  
  28. public function redo()
  29. {
  30. $this->execute();
  31. }
  32. }
  33.  
  34. class TurnOff implements Command
  35. {
  36. protected $bulb;
  37.  
  38. public function __construct(Bulb $bulb)
  39. {
  40. $this->bulb = $bulb;
  41. }
  42.  
  43. public function execute()
  44. {
  45. $this->bulb->turnOff();
  46. }
  47.  
  48. public function undo()
  49. {
  50. $this->bulb->turnOn();
  51. }
  52.  
  53. public function redo()
  54. {
  55. $this->execute();
  56. }
  57. }

Then we have an Invoker with whom the client will interact to process any commands

  1. // Invoker
  2. class RemoteControl
  3. {
  4. public function submit(Command $command)
  5. {
  6. $command->execute();
  7. }
  8. }

Finally let's see how we can use it in our client

  1. $bulb = new Bulb();
  2.  
  3. $turnOn = new TurnOn($bulb);
  4. $turnOff = new TurnOff($bulb);
  5.  
  6. $remote = new RemoteControl();
  7. $remote->submit($turnOn); // Bulb has been lit!
  8. $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

  1. class RadioStation
  2. {
  3. protected $frequency;
  4.  
  5. public function __construct(float $frequency)
  6. {
  7. $this->frequency = $frequency;
  8. }
  9.  
  10. public function getFrequency(): float
  11. {
  12. return $this->frequency;
  13. }
  14. }

Then we have our iterator

  1. use Countable;
  2. use Iterator;
  3.  
  4. class StationList implements Countable, Iterator
  5. {
  6. /** @var RadioStation[] $stations */
  7. protected $stations = [];
  8.  
  9. /** @var int $counter */
  10. protected $counter;
  11.  
  12. public function addStation(RadioStation $station)
  13. {
  14. $this->stations[] = $station;
  15. }
  16.  
  17. public function removeStation(RadioStation $toRemove)
  18. {
  19. $toRemoveFrequency = $toRemove->getFrequency();
  20. $this->stations = array_filter($this->stations, function (RadioStation $station) use ($toRemoveFrequency) {
  21. return $station->getFrequency() !== $toRemoveFrequency;
  22. });
  23. }
  24.  
  25. public function count(): int
  26. {
  27. return count($this->stations);
  28. }
  29.  
  30. public function current(): RadioStation
  31. {
  32. return $this->stations[$this->counter];
  33. }
  34.  
  35. public function key()
  36. {
  37. return $this->counter;
  38. }
  39.  
  40. public function next()
  41. {
  42. $this->counter++;
  43. }
  44.  
  45. public function rewind()
  46. {
  47. $this->counter = 0;
  48. }
  49.  
  50. public function valid(): bool
  51. {
  52. return isset($this->stations[$this->counter]);
  53. }
  54. }

And then it can be used as

  1. $stationList = new StationList();
  2.  
  3. $stationList->addStation(new RadioStation(89));
  4. $stationList->addStation(new RadioStation(101));
  5. $stationList->addStation(new RadioStation(102));
  6. $stationList->addStation(new RadioStation(103.2));
  7.  
  8. foreach($stationList as $station) {
  9. echo $station->getFrequency() . PHP_EOL;
  10. }
  11.  
  12. $stationList->removeStation(new RadioStation(89)); // Will remove station 89