• 技术文章 >后端开发 >php教程

    一起聊聊PHP中的备忘录模式

    青灯夜游青灯夜游2021-07-20 19:25:15转载586
    在之前的文章《深入浅析PHP中的建造者模式》中我们介绍了PHP中的建造者模式,下面本篇文章带大家了解一下PHP设计模式中的备忘录模式。

    备忘录,这个名字其实就已经很形象的解释了它的作用。典型的例子就是我们原来玩硬盘游戏时的存档功能。当你对即将面对的大BOSS有所顾虑时,一般都会先保存一次进度存档。如果挑战失败了,直接读取存档就可以恢复到挑战BOSS前的状态,然后你就开开心心的再去练一会级回来解决这个大BOSS就好了。不过,为了以防万一,在挑战BOSS之前存个档总是好的。另外一个例子就是我们码农们天天要用到的代码管理工具Git或者Svn了。每次的提交都像是一次存档备份,当新代码出现问题的时候,直接回滚恢复就行了。这些,都是备忘录模式的典型应用,下面就一起来看看这个模式吧。

    Gof类图及解释

    GoF定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态

    GoF类图:

    1.png

    代码实现:

    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;
        }
    }

    原发器,也可以叫做发起人。它有一个内部状态(state),这个状态可以在不同的情况下进行改变。当某一个事件发生时,需要将这个状态恢复到原先的状态。在这里,我们有一个CreateMemento()用于创建一个备忘录(存档),有一个SetMeneto()用于还原状态(读档)。

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

    备忘录,非常简单,就是用于记录状态。将这个状态以对象的形式保存,就可以让原发器非常方便地创建很多存档用于记录各种不同的状态。

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

    负责人,也叫做管理者类,保存备忘录,当需要的时候从这里取出备忘录。它只负责保存,不能修改备忘录。在复杂的应用中,可以将这里做成列表,就像游戏中可以选择性的展现多条存档记录供玩家选择。

    $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();

    客户端的调用中,我们的原发器初始化状态后进行了保存,然后人为的更改了状态。这时只需要通过负责人将状态还原回来就可以了。

    Mac的时光机功能大家有了解过吧,可以将电脑恢复到某一时间点的状态下。其实windows的ghost也是类似的功能。我们的手机操作系统上也决定开发这样的一个功能。当我们点击时光机备份时,将手机上所有的资料、数据、状态信息都压缩保存起来,如果用户允许的话,我们将这个压缩包上传到我们的云服务器上避免占用用户的手机内存,否则就只能保存到用户的手机内存中了。当用户的手机需要恢复到某个时间点,我们将所有的时光机备份列出,用户只需要用手指轻轻一按就可以把手机系统状态恢复到当时的样子了,是不是非常方便!!

    完整代码:https://github.com/zhangyue0503/designpatterns-php/blob/master/17.memento/source/memento.php

    实例

    这次又回到短信发送的例子上来。通常我们做短信或者邮件发送这些功能时,会有一个队列从数据库或者缓存中读取要发送的内容进行发送,如果成功了就不管了,如果失败了会将短信的状态改成失败或者重发。在这里,我们直接将它改回到之前未发送的状态然后等待下次发送的队列再次执行发送。

    短信发送类图

    2.png

    完整源码: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 = '未发送';
            $this->time = time();
        }
    
        public function Show()
        {
            echo $this->to, '---', $this->content, '---', $this->time, '---', $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('手机号' . $i, '内容' . $i);
        echo '初始状态:';
        $m->Show();
    
        // 保存初始信息
        $sc = new StateContainer();
        $sc->SetSaveState($m->CreateSaveSate());
        $scList[] = $sc;
    
        // 模拟短信发送,2发送成功,3发送失败
        $pushState = mt_rand(2, 3);
        $m->SetState($pushState == 2 ? '发送成功' : '发送失败');
        echo '发布后状态:';
        $m->Show();
    
        $mList[] = $m;
    }
    
    // 模拟另一个线程查找发送失败的并把它们还原到未发送状态
    sleep(2);
    foreach ($mList as $k => $m) {
        if ($m->GetState() == '发送失败') { // 如果是发送失败的,还原状态
            $m->SetSaveState($scList[$k]->GetSaveState());
        }
        echo '查询发布失败后状态:';
        $m->Show();
    }

    说明

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

    作者:硬核项目经理

    推荐学习:《PHP视频教程

    以上就是一起聊聊PHP中的备忘录模式的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金--硬核项目经理,如有侵犯,请联系admin@php.cn删除
    上一篇:PHP开发实例之公共方法【代码详解】 下一篇:解析PHP如何实现有趣的汉诺塔算法
    线上培训班

    相关文章推荐

    • 详解查看PHP版本的四种方法• PHP如何使用串口通信• 深入浅析PHP中的建造者模式• php怎么设置画布颜色• PHP中数组和字符串如何进行转换(必看)• 10个超级有用的PHP代码片段(建议收藏)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网