Design patterns

Unit: 11 of 18

In this lesson we will familiarize ourselves with design patterns in object-oriented programming. Although the word design suggests that it might be a graphical component of the application, design templates are actually far from that. These are actually pure program forms that relate exclusively to the structure of the application program.

What exactly is a design pattern? Nothing more than a solution to a standard programming problem. That solution was arrived at through evolution and empirically, and by using it we eliminate the phenomenon of “inventing hot water” in the creation of our application, which significantly speeds up production, especially if it is carried out in a team environment.

Templates are not something we can use by Copy/Paste. They are implemented in the object structure and form an integral part of it, with emphasis on the word “object”, because design patterns are closely related to the concept of object-oriented programming.

The number of templates available is large and in this lesson we will process only some of the most well-known and used templates in PHP. We’ll start with the simplest template,  the singleton .

Singleton pattern

Singleton pattern guarantees that you will create only one instance of a given object in your code. Let’s look at the example:

1
2
3
4
class MyClass { }
$a = new MyClass();
$b = new MyClass();
echo $a===$b;

This program will return false because the variables $a and $b do not represent the same object. This is completely logical behavior of the above program, but what if there is a database management system in the myClass class? Then we might want to make sure that the user can create multiple instances of the object, because then they would have multiple connections. In such cases, the best solution would be to use the singleton pattern:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MyClass{
private static $instance;
private function __construct(){        
}
public static function GetInstance(){
    if(!isset(self::$instance))
          self::$iinstance = new MyClass();
    return self::$instance;
}   
}
$a= MyClass::GetInstance();
$b= MyClass::GetInstance();
echo $a===$b;

The result of this example is true, where we got that two variables, i.e. two objects, hold the same instance of this class.

Observer

The Observer pattern allows the state of an object (Subject) to be transmitted to various objects (Subscribers) that monitor that object. This simple concept can be compared to a newspaper subscription. As long as the subscription is valid, the newspaper is delivered. When we cancel the subscription, the newspaper stops coming.

What we can technically highlight as clear units in the example of a newspaper is:

  • a list of all subscribers the publisher has;
  • how the publisher will deliver the edition to the subscriber.

So, in this template there are specific actors, which communicate with each other using specific methods. These methods are implemented through an interface – one for the subscriber (Observer) and the other for the provider (Distributor/Subject).

Let’s look at the implementation.

First we will create two interfaces: one for the Observer and the second for the Distributor. We know that the Observatory must have a method to notify it of new data. This can be the update method :

1
2
3
4
interface IObserver
{
  function update($sender, $args);  
}

The distributor must have methods for adding and canceling subscribers, as well as for sending the latest information. These can be addSubscriber, cancelSubscriber and sendUpdate methods:

1
2
3
4
5
6
interface IDistributor
{
 public function addSubscriber($p);
 public function removeSubscriber($p);
 public function sendUpdate();
}

When we create interfaces, we implement them in classes.

The Observer class is simpler. It must have an update method, because that’s how we specified it in the interface we were downloading (IObserver). Setting the variable  name in the constructor is not important for the template, we will only use it to be able to present the example as graphically as possible:

1
2
3
4
5
6
7
8
9
10
11
12
class Subscriber implements ISubscriber
{
   private $name;
   public function __construct($name)
   {
                 $this->name=$name;
   }
    public function update($sender, $eventArgs)
   {
        echo "Change: (" . $this->name . ") " . $eventArgs . "<br>";
   }
 }

The Distributor class is a bit more complicated because it needs to contain a list of all subscribers, with methods to subscribe and unsubscribe, as well as just send the latest information. It also implements the IDistributor interface, but this time:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Distributor implements IDistributor
{
private $allSubscribers;
public function addSubscriber($p)
{
 $this->allSubscribers[]=$p;  
}
public function removeSubscriber($p)
{
unset($this-> allSubscribers[array_search($p,$this->allSubscribers)]);
}
public function change()
{
$this->sendUpdate();
}
public function sendUpdate()
{
 foreach($this->allSubscribers as $pp)
    $pp->update($this,"Latest change");  
}
}

We see here that we have very simple methods defined in which there is nothing that we have not already learned before. Basically, we take that knowledge and apply it to a standard set of problems. To test if the template works, we can use a very simple example:

1
2
3
4
$d = new Distributor();
$d->addSubscriber(new Subscriber("p1"));
$d->addSubscriber(new Subscriber("p2"));
$d->change();


Factory

We use this template when we want to use an intermediate class, with the help of which we will create an instance of a certain class. Suppose we have several user classes in the system, from which we want to create a class, based on the program flow:

1
2
3
4
5
6
7
8
class CommonUser
{ public function __construct() { echo "Hello user!"; } }  
class Administrator
{ public function __construct() { echo "Hello administrator!"; } }  
class SuperAdministrator
{ public function __construct() { echo "Hello superadministrator!"; } }

To create the appropriate class, depending on the needs of the application or program, we use selection by type:

1
2
3
4
5
6
7
8
9
10
11
12
13
$type="Administrator";
switch($type)
      {
          case "CommonUser":
              $user = new CommonUser();
              break;
          case "Administrator":
              $user = new Administrator();
              break;
          case "SuperAdministrator":
              $user = new SuperAdministrator();
              break;
      }

To avoid such robustness and, in a certain way, also unreviewed code, we introduce a separate class, which will perform the selection in one place and create the corresponding instance. That class will actually be the Factory class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class FactoryClass
{
    public static function NewUser($type)
    {
     switch($tip)
        {
            case "ObicanKorisnik":
                return new ObicanKorisnik();
                break;
            case "Administrator":
                return new Administrator();
                break;
            case "SuperAdministrator":
                return new SuperAdministrator();
                break;
        }  
    }
}

After that, we create the object in the Factory class, and we only add the types later in one place, in the Factory class. We see that we also use the static method because this class does not need to be instantiated – it does not manage its own data or have any additional functionality. It just serves us as a simple wrapper that takes the abstraction to a higher level and makes our work easier:

1
$user = FactoryClass::NewUser("SuperAdministrator");


Decorator pattern

The Decorator pattern allows to modify (add to) the functionality of an existing class, where, unlike classical inheritance, the Decorator class is not in a direct hierarchical relationship with the class it “decorates”.

Let’s say we have a rectangle class that we want to modify. The initial class has an area calculation method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Rectangle
{
    public $a;
    public $b;
    public function __construct($a, $b)
    {
        $this->a = $a;
        $this->b = $b
    }
    public function surface()
    {
     return $this->a * $this->b;  
    }
}

This class is nothing new and unknown. We simply have two fields, a constructor, and a method to calculate the area of ​​the rectangle that uses the fields set via the constructor. After that, we create the Decorator class, which is nothing more than a wrapper for the base class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class RectangleDecorator
{
    protected $rectangle;
    protected $a;
    protected $b;
    
    public function __construct(Rectangle $rectangle)
    {
     $this->rectangle = $rectangle;
     $this->a = $this->rectangle->a;
     $this->b = $this->rectangle->b;
    }
    public function circumference()
    {
     return 2*($this->a+$this->b);  
    }
}

In the end, this is what the calls to the created classes will look like:

1
2
3
4
$p = new Rectangle(2,5);
echo $p-> surface();
$pd = new RectangleDecorator($p);
echo $pd-> circumference();

What we have actually done here is to pass the Decorator class a complete object from which it has taken the required fields or data and then proceeded to use its methods that rely on that data.

 

The Observer pattern allows the state of an object (Subject) to be transmitted to various objects (Subscribers) that monitor that object.


Model – View – Controller (MVC)

The MVC (model–view–controller) pattern is a pattern for creating applications, especially popular in web applications. It is characterized by three explicitly separate units: model, view and controller.

Image 11.1. MVC pattern illustration

The model is the part that contains concrete data (the data source manager), in the controller there is the working logic of the application, i.e. all its functionalities, while in the view there is the presentation logic, i.e. the GUI.

So let’s see the elements in more detail from the perspective of the web application layout.

  • The model in the application can refer to XML, JSON, and even database table structures. With the model we determine how the data is formatted and the logic that is applied; for example, we read data from the database differently than data from the XML file. In short: data manipulation (the database and the program code that knows how to manage the database).
  • View – as I mentioned, it represents the presentation logic, so it can be HTML and CSS; so the visual presentation of data in the program using, for example, tables, charts, lists and the like. Of course, here we can also add JavaScript as part of the view.
  • Controller – part of the application responsible for receiving user input and works directly with the model, i.e. with the application data. We can say that the Controller is our connection between the Model and the View.

A simplified example for the MVC design pattern would be the following:

The user enters data into the registration form, the input is downloaded and processed and then stored in the database. This would be the view–controller–model relationship.

Conversely, we would have the following situation. Data is received from the model, formatted and displayed to the user. Then this would be the movement of data in the model-controller-view relationship.

The MVC pattern is characterized by the entry point into the application. This is usually the index page, which serves as a dispatcher of requests received from users.

We can write the MVC template ourselves, but we can also use some of the ready-made templates, which is the best option.

Let’s now see a very simplified example of the MVC pattern:

1
2
3
4
5
6
class Model {
    public $data;
    public function __construct() {
        $this->data = 'Hello world!';
    }
}

We start with the definition of the Model class, so within it is our data. Of course, in practice, this would be processing external files or database queries, but for our example, in the class constructor, we just set the Hello World value. Now the Model class represents our application data.

Following is the definition of the View part:

1
2
3
4
5
6
7
8
9
class View {
    public $controller;
    public function __construct(Controller $controller) {
        $this->controller = $controller;
    }
  public function output() {
        return '<h1>' . $this->controller->getData() .'</h1>';
    }
}

Within the View class we have a property called controller. As I said earlier, the View takes the processed data from the controller and displays it. So in the constructor of the class we specify the controller to be used as a parameter and set the value. Within the class, we also have the output method, which will have the purpose of printing the value. As you can see, the value will be printed inside the h1 tag, and we get the value through the controller object and the getData method, so let’s see that part of the code:

1
2
3
4
5
6
7
8
9
class Controller {
        private $model
public function getData(){
return $this->model->data;
}
      public function __construct(Model $model) {
        $this->model = $model;
      
}

So this is the Controller class. Its purpose is to retrieve data from the model. With the constructor, we define which class model it receives. Finally, it remains to instantiate the classes and connect the application.

1
2
3
4
$model = new Model();
$controller = new Controller($model);
$view = new View($controller);
echo $view->controller->output();

So, in the controller we process the data from the model, then in the View we take the data from the controller and finally the line: echo $view->controller>output();

We call the output method and present the result.

On the following link you can read an interesting article about MVC design pattern or MVC architecture:

https://www.freecodecamp.org/news/model-view-architecture/?fbclid=IwAR2aNJ2eofS-Jv_lHamjkF7gKsn0y3bATsamlQvHshaN39RNu237o9KalaA

It is important to remember that in the case of MVC, we have some framework rules, namely a working system, but the implementation of that architecture differs from case to case. That’s why you can write your own MVC design pattern as you see fit, still following the rules of this architecture. In this article you can find a simple tutorial on how to create the simplest version of the MVC template:

https://www.giuseppemaccario.com/how-to-build-a-simple-php-mvc-framework/

You can find all the design templates on this link:

https://refactoring.guru/design-patterns/php

Along with additional examples and clarifications.

Leave a Reply

Your email address will not be published. Required fields are marked *