Home  >  Article  >  Backend Development  >  Let’s talk about the memo mode in PHP

Let’s talk about the memo mode in PHP

青灯夜游
青灯夜游forward
2021-07-20 19:25:152176browse

In the previous article "In-depth analysis of the builder pattern in PHP" we introduced the builder pattern in PHP. The following article will take you to understand the memo pattern in PHP design pattern. .

Let’s talk about the memo mode in PHP

Memo, this name actually explains its function very vividly. A typical example is the archive function when we originally played hard disk games. When you are worried about the big BOSS you are about to face, you usually save a progress archive first. If the challenge fails, you can directly read the archive to restore to the state before challenging the BOSS. Then you can happily practice for a while and come back to solve the big BOSS. However, just in case, it's always a good idea to save a file before challenging the BOSS. Another example is Git or Svn, the code management tools that we programmers use every day. Each submission is like an archive backup. When there is a problem with the new code, just roll back and recover. These are all typical applications of the memo mode. Let’s take a look at this mode together.

Gof class diagram and explanation

GoF definition: Capture the internal state of an object without destroying encapsulation, and Save this state outside of this object. In this way, the object can be restored to its original saved state

GoF class diagram:

Let’s talk about the memo mode in PHP

Code implementation:

class Originator
{
    private $state;
    public function SetMeneto(Memento $m)
    {
        $this->state = $m->GetState();
    }
    public function CreateMemento()
    {
        $m = new Memento();
        $m->SetState($this->state);
        return $m;
    }

    public function SetState($state)
    {
        $this->state = $state;
    }

    public function ShowState()
    {
        echo $this->state, PHP_EOL;
    }
}

The originator can also be called the initiator. It has an internal state that can change under different circumstances. When an event occurs, this state needs to be restored to its original state. Here, we have a CreateMemento() for creating a memo (archive) and a SetMeneto() for restoring the state (reading the file).

class Memento
{
    private $state;
    public function SetState($state)
    {
        $this->state = $state;
    }
    public function GetState()
    {
        return $this->state;
    }
}

Memo, very simple, is used to record status. Saving this state in the form of an object allows the originator to easily create many archives to record various states.

class Caretaker
{
    private $memento;
    public function SetMemento($memento)
    {
        $this->memento = $memento;
    }
    public function GetMemento()
    {
        return $this->memento;
    }
}

The person in charge, also called the manager class, saves the memo and takes out the memo from here when needed. It is only responsible for saving and cannot modify the memo. In complex applications, this can be made into a list, just like a game that can selectively display multiple archive records for players to choose from.

$o = new Originator();
$o->SetState('状态1');
$o->ShowState();

// 保存状态
$c = new Caretaker();
$c->SetMemento($o->CreateMemento());

$o->SetState('状态2');
$o->ShowState();

// 还原状态
$o->SetMeneto($c->GetMemento());
$o->ShowState();

In the client call, our originator initialized the state and saved it, and then artificially changed the state. At this time, you only need to restore the status through the person in charge.

  • To put it bluntly, the memo mode is to let an external class B save the internal state of A, and then easily restore this state at the appropriate time.
  • There are actually many application scenarios for the memo mode, such as browser rollback, database backup and restore, operating system backup and restore, document undo and redo, chess and card game regrets, etc.
  • This mode can maintain the encapsulation of the originator, that is, these states need to be hidden from external objects, so it can only be handed over to a memo object to record
  • The copying possibility of the state between the originator and the memo It will bring performance problems, especially the complex and numerous internal states of large objects, and it will also bring some coding loopholes, such as missing some states

Mac's time machine function Everyone knows that you can restore your computer to a state at a certain point in time. In fact, Windows ghost also has a similar function. Our mobile operating system also decided to develop such a function. When we click Time Machine Backup, all the information, data, and status information on the phone will be compressed and saved. If the user allows it, we will upload the compressed package to our cloud server to avoid occupying the user's phone memory. Otherwise, it will It can only be saved to the user's mobile phone memory. When the user's mobile phone needs to be restored to a certain point in time, we will list all the time machine backups. The user can restore the mobile phone system status to what it was at that time with just a tap of a finger. Isn't it very convenient! !

Full code: https://github.com/zhangyue0503/designpatterns-php/blob/master/17.memento/source/memento.php

Example

This time we return to the example of sending text messages. Usually when we do SMS or email sending functions, there will be a queue that reads the content to be sent from the database or cache and sends it. If it succeeds, it will be ignored. If it fails, the status of the SMS will be changed to failed or resent. . Here, we directly change it back to the previous unsent state and then wait for the next sending queue to perform sending again.

SMS sending class diagram

Let’s talk about the memo mode in PHP

Full source code: https://github.com/zhangyue0503/designpatterns-php /blob/master/17.memento/source/memento-message.php

<?php
class Message
{
    private $content;
    private $to;
    private $state;
    private $time;

    public function __construct($to, $content)
    {
        $this->to = $to;
        $this->content = $content;
        $this->state = &#39;未发送&#39;;
        $this->time = time();
    }

    public function Show()
    {
        echo $this->to, &#39;---&#39;, $this->content, &#39;---&#39;, $this->time, &#39;---&#39;, $this->state, PHP_EOL;
    }

    public function CreateSaveSate()
    {
        $ss = new SaveState();
        $ss->SetState($this->state);
        return $ss;
    }

    public function SetSaveState($ss)
    {
        if ($this->state != $ss->GetState()) {
            $this->time = time();
        }
        $this->state = $ss->GetState();
    }

    public function SetState($state)
    {
        $this->state = $state;
    }

    public function GetState()
    {
        return $this->state;
    }

}

class SaveState
{
    private $state;
    public function SetState($state)
    {
        $this->state = $state;
    }
    public function GetState()
    {
        return $this->state;
    }
}

class StateContainer
{
    private $ss;
    public function SetSaveState($ss)
    {
        $this->ss = $ss;
    }
    public function GetSaveState()
    {
        return $this->ss;
    }
}

// 模拟短信发送
$mList = [];
$scList = [];
for ($i = 0; $i < 10; $i++) {
    $m = new Message(&#39;手机号&#39; . $i, &#39;内容&#39; . $i);
    echo &#39;初始状态:&#39;;
    $m->Show();

    // 保存初始信息
    $sc = new StateContainer();
    $sc->SetSaveState($m->CreateSaveSate());
    $scList[] = $sc;

    // 模拟短信发送,2发送成功,3发送失败
    $pushState = mt_rand(2, 3);
    $m->SetState($pushState == 2 ? &#39;发送成功&#39; : &#39;发送失败&#39;);
    echo &#39;发布后状态:&#39;;
    $m->Show();

    $mList[] = $m;
}

// 模拟另一个线程查找发送失败的并把它们还原到未发送状态
sleep(2);
foreach ($mList as $k => $m) {
    if ($m->GetState() == &#39;发送失败&#39;) { // 如果是发送失败的,还原状态
        $m->SetSaveState($scList[$k]->GetSaveState());
    }
    echo &#39;查询发布失败后状态:&#39;;
    $m->Show();
}

说明

  • 短信类做为我们的原发器,在发送前就保存了当前的发送状态
  • 随机模拟短信发送,只有两个状态,发送成功或者失败,并改变原发器的状态为成功或者失败
  • 模拟另一个线程或者脚本对短信的发送状态进行检查,如果发现有失败的,就将它重新改回未发送的状态
  • 这里我们只是保存了发送状态这一个字段,其他原发器的内部属性并没有保存
  • 真实的场景下我们应该会有一个重试次数的限制,当超过这个次数后,状态改为彻底的发送失败,不再进行重试了

原文地址:https://juejin.cn/post/6844903983555805192

作者:硬核项目经理

推荐学习:《PHP视频教程

The above is the detailed content of Let’s talk about the memo mode in PHP. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.cn. If there is any infringement, please contact admin@php.cn delete