php design patterns, their own understanding and code development

Posted by Jezz on Mon, 20 Sep 2021 08:20:45 +0200

At present, five modes are introduced: single case mode, factory mode, registration mode, strategy mode, observer mode and decorator mode

1. Single case mode

Simply understand all privatization, and only open static methods to call other methods of this class

<?php
//Single case
class Uni{
        //Create a static private variable to hold the class object
    static private $instance;
        //parameter
    private $config;
        //Prevent direct creation of objects
    private function __construct($config){
        $this -> config = $config;
                echo "I was instantiated";
    }
        //Prevent cloning objects
    private function __clone(){

    }
    static public function getInstance($config){
                //Determine whether $instance is a Uni object
                //Not created
        if (!self::$instance instanceof self) {
            self::$instance = new self($config);
        }
        return self::$instance;

    }
    public function getName(){
        echo $this -> config;
    }
}
$db1 = Uni::getInstance(1);
$db1 -> getName();
echo "<br>";
$db2 = Uni::getInstance(4);
$db2 -> getName();
?>

2. Factory mode

Factory patterns, factory methods or classes generate objects instead of new directly in the code.
Using factory mode can avoid modifying the name or parameters of a class in all the code calling the class after changing its name or method. In fact, it has the same meaning as a single class

Test1.php
<?php
class Test1{
    static function test(){
        echo __FILE__;
    }
}

Factory.php
<?php
class Factory{
    /*
     * If a class has new ClassName() in many files, what if the name of the class
     * If there is a change or parameter change, you need to modify every PHP if you do not use factory mode
     * After using the factory pattern, you only need to modify the factory class or method.
     */
    static function createDatabase(){
        $test = new Test1();
        return $test;
    }
}

Test.php
<?php
spl_autoload_register('autoload1');

$test = Factory::createDatabase();
$test->test();
function autoload1($class){
    $dir  = __DIR__;
    $requireFile = $dir."\\".$class.".php";
    require $requireFile;
}
Test1.php
<?php
class Test1{
    protected static  $tt;
    private function __construct(){}
    static function getInstance(){
        if(self::$tt){
            echo "Object has been created<br>";
            return self::$tt;
        }else {
            self::$tt = new Test1();
            echo "create object<br>";
            return self::$tt;
        }
    }
     function echoHello(){
        echo "Hello<br>";
    }
}
Test.php
<?php
spl_autoload_register('autoload1');

$test = Test1::getInstance();
$test->echoHello();
$test = Test1::getInstance();
$test->echoHello();
$test = Test1::getInstance();
$test->echoHello();
$test = Test1::getInstance();
$test->echoHello();
function autoload1($class){
    $dir  = __DIR__;
    $requireFile = $dir."\\".$class.".php";
    require $requireFile;
}

3. Registration mode

Registration mode to solve global sharing and exchange objects. The created object is hung on an array that can be used globally. When it needs to be used, it can be obtained directly from the array. Register the object on the global tree. Visit directly anywhere.

<?php

class Register
{
    protected static  $objects;
    function set($alias,$object)//Register objects on the global tree
    {
        self::$objects[$alias]=$object;//Place the object on the tree
    }
    static function get($name){
        return self::$objects[$name];//Gets an object registered in the tree
    }
    function _unset($alias)
    {
        unset(self::$objects[$alias]);//Remove an object registered to the tree.
    }
}

4. Strategy mode

Policy pattern encapsulates a set of specific behaviors and algorithms into classes to adapt to some specific context.
eg: if there is an e-commerce website system, male and female users should jump to different commodity categories, and all advertising spaces display different advertisements. In the traditional code, all kinds of if else judgment and hard coding are added to the system. If you add a user one day, you need to rewrite the code. Using the policy mode, if you add a new user type, you only need to add a policy. All other places just need to use different strategies.
First, declare the interface file of the policy, and stipulate the behavior of the policy. Then, each specific policy implementation class is defined.

UserStrategy.php
<?php
/*
 * Declare the interface of the policy file and agree on the behavior contained in the policy.
 */
interface UserStrategy
{
    function showAd();
    function showCategory();
}
FemaleUser.php
<?php
require_once 'Loader.php';
class FemaleUser implements UserStrategy
{
    function showAd(){
        echo "2016 Winter women's wear";
    }
    function showCategory(){
        echo "Women's wear";
    }
}
MaleUser.php
<?php
require_once 'Loader.php';
class MaleUser implements UserStrategy
{
    function showAd(){
        echo "IPhone6s";
    }
    function showCategory(){
        echo "electronic product";
    }
}
Page.php//Executive document
<?php
require_once 'Loader.php';
class Page
{
    protected $strategy;
    function index(){
        echo "AD";
        $this->strategy->showAd();
        echo "<br>";
        echo "Category";
        $this->strategy->showCategory();
        echo "<br>";
    }
    function setStrategy(UserStrategy $strategy){
        $this->strategy=$strategy;
    }
}

$page = new Page();
if(isset($_GET['male'])){
    $strategy = new MaleUser();
}else {
    $strategy = new FemaleUser();
}
$page->setStrategy($strategy);
$page->index();

Summary:
Through the above methods, it can be found that different contents are displayed when different users log in, but the problem of hard coding during display is solved. If you want to add a policy, you only need to add a policy implementation class, then execute judgment in the entry file and pass in this class. Decoupling is realized.
Implement dependency inversion and control inversion (to be understood)
Through the interface, there is no direct dependency between classes. When using this class, an implementation class of the interface is dynamically passed in. If you want to replace a class, you only need to provide an implementation class that implements the interface, and you can complete the replacement by modifying a line of code.

5. Observer mode

1: Observer mode: when the state of an object changes, all objects that depend on it will be notified and updated automatically.
2: Scenario: after an event occurs, a series of update operations are performed. The traditional programming method is to add processing logic directly after the event code. As the updated logic increases, the code becomes difficult to maintain. This method is coupled and intrusive. Adding new logic requires modifying the body code of the event.
3: Observer mode implements a low coupling, non-invasive notification and update mechanism.
Define an event trigger abstract class.

EventGenerator.php
<?php
require_once 'Loader.php';
abstract class EventGenerator{
    private $observers = array();
    function addObserver(Observer $observer){
        $this->observers[]=$observer;
    }
    function notify(){
        foreach ($this->observers as $observer){
            $observer->update();
        }
    }
}
Observer.php
<?php
require_once 'Loader.php';
interface Observer{
    function update();//Here is the logic to be executed after the event
}
<?php
//A class that implements the EventGenerator abstract class, which is used to specifically define an event that occurs
require 'Loader.php';
class Event extends EventGenerator{
    function triger(){
        echo "Event<br>";
    }
}
class Observer1 implements Observer{
    function update(){
        echo "Logic 1<br>";
    }
}
class Observer2 implements Observer{
    function update(){
        echo "Logic 2<br>";
    }
}
$event = new Event();
$event->addObserver(new Observer1());
$event->addObserver(new Observer2());
$event->triger();
$event->notify();

6. Decorator mode

Decorator mode, also known as decorator mode, dynamically extends the function of an object without changing the original class file and using inheritance. The traditional programming mode is that the subclass inherits the overloaded implementation method of the parent class. Using the decorator mode, you only need to add a new decorator object, which is more flexible and avoids too many classes and levels.

<?php
namespace Libs;
/**
 * Decorated object base class
 * */
interface Component
{
    /**
     * Calculate the required cost
     * */
    public function cost();
}
<?php
namespace Libs;

/**
 * Define the specific object to be decorated. Here is the steamed stuffed bun of the staple food
 * */
class ConcreteComponentBun implements Component
{
    public function __construct()
    {
        echo "Oh,There is the construct of ConcreteComponentBun.</br>";
    }
    public function cost()
    {
        echo "There is the function of ConcreteComponentBun named cost. <br/>";
        return 15.00;
    }
}
<?php
namespace  Libs;
/**
 * Decorator interface
 * */
class Decorator implements Component
{
    public function __construct()
    {
        $this->_name = 'Decorator';
    }
    public function cost()
    {
        return 1.00;
    }

}
<?php
namespace Libs;

class ConcreteDecoratorSalad extends Decorator
{
    public $_component;
    public function __construct($component)
    {
        echo "Oh,There is the construct of ConcreteDecoratorSalad.</br>";
        
        if($component instanceof Component){
            $this->_component = $component;
        } else {
            exit('Failure');
        }
    }
    public function cost()
    {
        echo "There is the function of ConcreteDecoratorSalad named cost. <br/>";
        return $this->_component->cost()+10.00;
    }
}
<?php
namespace Libs;

class ConcreteDecoratorSoup extends Decorator
{
    public $_component;
    public function __construct($component)
    {
        echo "Oh,There is the construct of ConcreteDecoratorSoup.</br>";
        if($component instanceof Component){
            $this->_component = $component;
        } else {
            exit('Failure');
        }
    }
    public function cost()
    {
        echo "There is the function of ConcreteDecoratorSoup named cost. <br/>";
        return $this->_component->cost()+5.00;
    }

}
<?php
namespace Libs;

class UseDecorator
{
    public static function index()
    {
        
        $bun = new ConcreteComponentBun();
        $cost = $bun->cost();
        echo "The cost is {$cost} <br>";
        echo "_________________________________________________</br>";
        
        $salad_bun = new ConcreteDecoratorSalad($bun);
        $cost = $salad_bun->cost();
        echo "The cost is {$cost} <br>";
        echo "_________________________________________________</br>";
        
        $soup_bun = new ConcreteDecoratorSoup($bun);
        $cost = $soup_bun->cost();
        echo "The cost is {$cost} <br>";
        echo "_________________________________________________</br>";
        
    }
}

advantage:
1). The purpose of Decorator pattern and inheritance relationship is to extend the function of objects, but Decorator can provide more flexibility than inheritance.
2). By using different specific decorative categories and the arrangement and combination of these decorative categories, designers can create many combinations of different behaviors.

Disadvantages:
1). This feature, which is more flexible than inheritance, also means more complexity.
2). Decoration mode will lead to many small classes in the design. If it is overused, the program will become very complex.
3). Decoration mode is programmed for abstract Component type. However, if you want to program for specific components, you should rethink your application architecture and whether the decorator is appropriate. Of course, you can also change the Component interface, add new public behavior, and realize the "translucent" decorator mode. Make the best choice in the actual project.

Topics: PHP