Three design patterns commonly used in PHP are explained in detail [singleton pattern, factory pattern, observer pattern]

Time:2019-8-10

Three design patterns commonly used in PHP are illustrated with examples in this paper. Share for your reference, as follows:

Three design modes commonly used in PHP: singleton mode, factory mode and observer mode

1. Singleton Model

Why use PHP singleton mode?

Most people understand its use literally from the meaning of singleton mode, which is a kind of “family planning” because it saves system resources and avoids repeated instantiation. Every time a page is executed, PHP will clean up all resources from memory. Hence, every single instance in PHP needs to run heavily. New instantiation, which loses the meaning of repeated instantiation of singletons. In this respect alone, PHP singletons do disappoint you a little. But is singleton only this function and application? The answer is No.

  1. PHP is mainly used in database applications, so there will be a large number of database operations in an application. When using object-oriented development (nonsense), if using the singleton mode, it can avoid a large number of resources consumed by new operations.
  2. If a class is needed in the system to control some configuration information globally, it can be easily implemented using the singleton pattern. This can be seen in the FrontController section of the Zend Framework.
  3. In a page request, it is easy to debug because all the code (such as database operation class db) is concentrated in one class. We can set hooks in the class and output logs to avoid var_dump, echo everywhere.

A single case class should include the following points:

Unlike ordinary classes, singleton classes cannot be instantiated directly, but only by themselves. Therefore, in order to achieve such a restrictive effect, the constructor must be marked asprivate

In order for a singleton class to work without being instantiated directly, it must be provided with such an instance. Therefore, it is necessary for a singleton class to have a private static member variable that can hold an instance of the class and a corresponding public static method that can access the instance.

In PHP, to prevent cloning of singleton class objects to break the above implementation of singleton classes, it is often provided with an empty private__clone()Method.

For an object of a class, if the “clone operator” is used, a new object identical to the current object will be copied out, and the magic method of this class will be automatically invoked at this time:__clone()As long as there is a method in this class.

In order to realize the singleton class, we should “prohibit cloning” the object of the singleton class, and use private to modify _clone() to achieve the prohibition of cloning. Specifically, we can refer to the strengthening of the singleton class: prohibiting cloning.

Examples of the singleton pattern:

<?php
/**
* Design pattern singleton pattern
* $instance must be declared as a static private variable
* Constructors and destructors must be declared private to prevent new external programs
* Classes thus lose the meaning of the singleton pattern
* The getInstance () method must be set to public and must be called
* To return a reference to an instance
*:: Operators can only access static variables and static functions
* New objects consume memory
* Use scenarios: The most common place is the database connection.
* After using the singleton pattern to generate an object,
* This object can be used by many other objects.
*/
class SingetonBasic {
Private static $instance; // Privatize static variables to prevent out-of-class modifications
// other vars..
Private function _construct() {// constructor privatization, no new objects can be created directly outside the class
  // do construct..
}
Private function clone () {}/// Private before clone () to prohibit cloning
Public static function getInstance () {// public static method, public - external interface, static - access by class name instead of using objects
  If (!) (self:: $instance of self){//private static variable $instance is empty
    Self:: $instance = new self (); // New as its own object and assign it to the private variable $instance
  }
  Return self:: $instance; // Return private variable $instance
}
// other functions..
}
$a = SingetonBasic::getInstance();
$b = SingetonBasic::getInstance();
Var_dump ($a=== $b); // The result is Boolean true
//?>
<?php
/**
 * PHP singleton, why can singleton pattern only be instantiated once
*/
class Example{
  // Save class instances in this property
  private static $instance;
  // The constructor is declared private to prevent direct creation of objects
  private function __construct(){
    echo 'I am constructed';
  }
  // singleton method
  public static function singleton(){
    If (! Isset (self:: $instance) {// Determine whether an instance of the current class was created before
      $c = CLASS_; // Get the class name
      Self:: $instance = new $c; // If not created, instantiate the current class, where the implementation class is instantiated only once
    }
    Return self:: $instance;//return instance of class
  }
  // Common methods in Example classes
  public function bark(){
    echo 'Woof!';
  }
  // Prevent users from copying object instances
  public function __clone(){
    trigger_error('Clone is not allowed.', E_USER_ERROR);
  }
}
// This is incorrect because the constructor is declared private
$test = new Example;
// Next you will get the singleton object of the Example class
$test = Example::singleton();
$test->bark();
// Next you will get the singleton object of the Example class
$test = Example::singleton();
$test->bark();
// Copying objects will result in an E_USER_ERROR.
$test_clone = clone $test;
?>

about__clone()Method Reference: Introduction of PHP Object Cloning _clone()

2. Factory Model

The factory pattern is based on creating a class that is specifically designed to implement and return instances of other classes, depending on the input parameters or application configuration.

Examples of factory models:


<?php
class FactoryBasic {
  public static function create($config) {
  }
}

For example, here is a factory that describes shape objects. It wants to create different shapes according to the number of parameters passed in.

<?php
// Common function for defining shapes: Get circumference and area.
interface IShape {
  function getCircum();
  function getArea();
}
// Define Rectangular Classes
class Rectangle implements IShape {
  private $width, $height;
  public function __construct($width, $height) {
    $this->width = $width;
    $this->height = $height;
  }
  public function getCircum() {
    return 2 * ($this->width + $this->height);
  }
  public function getArea() {
    return $this->width * $this->height;
  }
}
// Define circle classes
class Circle implements IShape {
  private $radii;
  public function __construct($radii) {
    $this->radii = $radii;
  }
  public function getCircum() {
    return 2 * M_PI * $this->radii;
  }
  public function getArea() {
    return M_PI * pow($this->radii, 2);
  }
}
// Different shapes are created according to the number of parameters passed in.
class FactoryShape {
  public static function create() {
    switch (func_num_args()) {
      case 1:
      return new Circle(func_get_arg(0));
      break;
      case 2:
      return new Rectangle(func_get_arg(0), func_get_arg(1));
      break;
    }
  }
}
// Rectangular object
$c = FactoryShape::create(4, 2);
var_dump($c->getArea());
// circular object
$o = FactoryShape::create(2);
var_dump($o->getArea());

Using factory mode makes it easier to invoke methods because it has only one class and one method. If factory mode is not used, it is necessary to decide which class and method should be invoked at the time of invocation. Using factory mode also makes it easier to make future changes to applications, such as adding a shape. To support this, you only need to modify one method of create () in the factory class, instead of using factory mode, you need to modify the code block of the invocation shape.

3. Observer model

The observer pattern gives you another way to avoid tight coupling between components. The pattern is very simple: an object makes itself observable by adding a method that allows another object, the observer, to register itself. When an observable object changes, it sends a message to a registered observer. The operations performed by these observers using this information are independent of the observable objects. As a result, objects can talk to each other without knowing why.

A simple example: When the listener is listening to the radio (that is, the radio joins a new listener), it will send a prompt message, which can be observed by the log observer sending the message.

<?php
// Observer interface
interface IObserver {
  function onListen($sender, $args);
  function getName();
}
// Observable interface
interface IObservable {
  function addObserver($observer);
  function removeObserver($observer_name);
}
// Observers
abstract class Observer implements IObserver {
  protected $name;
  public function getName() {
    return $this->name;
  }
}
// Observable class
class Observable implements IObservable {
  protected $observers = array();
  public function addObserver($observer) {
    if (!($observer instanceof IObserver)) {
      return;
    }
    $this->observers[] = $observer;
  }
  public function removeObserver($observer_name) {
    foreach ($this->observers as $index => $observer) {
      if ($observer->getName() === $observer_name) {
        array_splice($this->observers, $index, 1);
        return;
      }
    }
  }
}
// Simulate a class that can be observed: RadioStation
class RadioStation extends Observable {
  public function addListener($listener) {
    foreach ($this->observers as $observer) {
      $observer->onListen($this, $listener);
    }
  }
}
// Simulate an observer class
class RadioStationLogger extends Observer {
  protected $name = 'logger';
  public function onListen($sender, $args) {
    echo $args, ' join the radiostation.<br/>';
  }
}
// Simulate another Observer class
class OtherObserver extends Observer {
  protected $name = 'other';
  public function onListen($sender, $args) {
    echo 'other observer..<br/>';
  }
}
$rs = new RadioStation();
// Inject the observer
$rs->addObserver(new RadioStationLogger());
$rs->addObserver(new OtherObserver());
// Remove the observer
$rs->removeObserver('other');
// Observed information can be seen
$rs->addListener('cctv');
?>

More readers interested in PHP-related content can see the topics of this site: Introduction to Php Object-Oriented Programming, Introduction to PHP Array Operating Skills, Introduction to PHP Basic Grammar, Summary of PHP Operating and Operator Usage, Summary of Php String Usage, and php+mysql Data. Introduction to Library Operations and Summary of Common Database Operating Skills in PHP

I hope this article will be helpful to everyone’s PHP program design.

Recommended Today

Implementation of PHP Facades

Example <?php class RealRoute{ public function get(){ Echo’Get me’; } } class Facade{ public static $resolvedInstance; public static $app; public static function __callStatic($method,$args){ $instance = static::getFacadeRoot(); if(!$instance){ throw new RuntimeException(‘A facade root has not been set.’); } return $instance->$method(…$args); } // Get the Facade root object public static function getFacadeRoot() { return static::resolveFacadeInstance(static::getFacadeAccessor()); } protected […]