Skip to content

Latest commit

 

History

History
211 lines (163 loc) · 5.21 KB

8.md

File metadata and controls

211 lines (163 loc) · 5.21 KB

#Lesson 8: Design Patterns

##Program to an interface, not an implementation.

We learned an interface is a set of methods that an object responds to, and an implentation is the code and logic for the object. Generally you want to write code you want to reference interfaces instead of implementations.

This decouples design from the specific implementation of concrete classes, and allows you to swap out one implementation for another easily, as well as create new implementations.

In PHP we can accomplish this by specifying interface data types in type hinting as shown in the lesson 6 Client class example. It is important to note that by 'interface data types', we mean interfaces or abstract classes.

Also, as previously noted, we can instantiate an object of a given concrete implementation, and so long as it implements an interface or extends an abstract class, those parent classes will be used to identify the object curing type hinting.

##Favor object composition over class inheritance.

If at all possible, try to create client classes that are composed of various objects.

Consider the following classes:

  1. Inheritance
<?php

class Pet {
  function speak() {
    echo 'speaking';
  }
}

class Dog extends Pet {
  function bite() {
    echo '\/\/\/';
  }
}

class Client {
  function __construct() {
    $dog = new Dog();
  }
}

This contrived example shows a client class that uses an object.

##Strategy

Encapsulates specific families of algorithms allowing the client class responsible for instantiating a particular algorithm to have no knowledge of the actual implementation.

<?php

interface OutputInterface
{
    public function load();
}

class SerializedArrayOutput implements OutputInterface
{
    public function load()
    {
        return serialize($arrayOfData);
    }
}

class JsonStringOutput implements OutputInterface
{
    public function load()
    {
        return json_encode($arrayOfData);
    }
}

class ArrayOutput implements OutputInterface
{
    public function load()
    {
        return $arrayOfData;
    }
}

##Dependency Injection

In Drupal 8 dependency injection is the preferred method for accessing and using services. Services are reusable functionality (e.g. database connection, string translation, cacheing, authentication) that are made pluggable and replaceable via dependency injection.

An injection is the passing of a dependency (a service) to a dependent object (a client). The service is made part of the client's state. Passing the service to the client, rather than allowing a client to build or find the service, is the fundamental requirement of the pattern.

Some of the design patterns that preceded DI:

###Singleton

A singleton is a class that is intended to be instantiated once and reused in multiple scopes in an application.

<?php

class Singleton
{
    /**
     * Returns the *Singleton* instance of this class.
     *
     * @staticvar Singleton $instance The *Singleton* instances of this class.
     *
     * @return Singleton The *Singleton* instance.
     */
    public static function getInstance()
    {
        static $instance = null;
        if (null === $instance) {
            $instance = new static();
        }

        return $instance;
    }

    /**
     * Protected constructor to prevent creating a new instance of the
     * *Singleton* via the `new` operator from outside of this class.
     */
    protected function __construct()
    {
    }

    /**
     * Private clone method to prevent cloning of the instance of the
     * *Singleton* instance.
     *
     * @return void
     */
    private function __clone()
    {
    }

    /**
     * Private unserialize method to prevent unserializing of the *Singleton*
     * instance.
     *
     * @return void
     */
    private function __wakeup()
    {
    }
}

class SingletonChild extends Singleton
{
}

$obj = Singleton::getInstance();
var_dump($obj === Singleton::getInstance());             // bool(true)

$anotherObj = SingletonChild::getInstance();
var_dump($anotherObj === Singleton::getInstance());      // bool(false)

var_dump($anotherObj === SingletonChild::getInstance()); // bool(true)

###Factory

A factory class simply creates the object you want to use. The purpose of the factory patterns is to separate the use of a certain component, from the choice of implementation + instance management of that component.

<?php

class Automobile
{
    private $vehicleMake;
    private $vehicleModel;

    public function __construct($make, $model)
    {
        $this->vehicleMake = $make;
        $this->vehicleModel = $model;
    }

    public function getMakeAndModel()
    {
        return $this->vehicleMake . ' ' . $this->vehicleModel;
    }
}

class AutomobileFactory
{
    public static function create($make, $model)
    {
        return new Automobile($make, $model);
    }
}

// have the factory create the Automobile object
$veyron = AutomobileFactory::create('Bugatti', 'Veyron');

print_r($veyron->getMakeAndModel()); // outputs "Bugatti Veyron"

##References