美文网首页
PHP设计模式之备忘录模式(Memento)代码实例大全(25)

PHP设计模式之备忘录模式(Memento)代码实例大全(25)

作者: 八重樱勿忘 | 来源:发表于2020-09-18 16:01 被阅读0次

    目的

    它提供了在不破坏封装(对象不需要具有返回当前状态的函数)的情况下恢复到之前状态(使用回滚)或者获取对象的内部状态。

    备忘录模式使用 3 个类来实现:Originator,Caretaker 和 Memento。

    Memento —— 负责存储 Originator 的 唯一内部状态 ,它可以包含: string,number, array,类的实例等等。Memento 「不是公开的类」(任何人都不应该且不能更改它),并防止 Originator 以外的对象访问它,它提供 2 个接口:Caretaker 只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。Originator 却可看到备忘录的宽接口,允许它访问返回到先前状态所需要的所有数据。

    Originator —— 它负责创建 Memento ,并记录 外部对象当前时刻的状态, 并可使用 Memento 恢复内部状态。Originator 可根据需要决定 Memento 存储 Originator 的哪些内部状态。 Originator 也许(不是应该)有自己的方法(methods)。 但是,他们 不能更改已保存对象的当前状态。

    Caretaker —— 负责保存 Memento。 它可以修改一个对象;决定 Originator 中对象当前时刻的状态; 从 Originator 获取对象的当前状态; 或者回滚 Originator 中对象的状态。

    例子

    • 保存之前控制 ORM Model 中的状态

    • 并将这个随机数存在时序机中

    • 发送一个随机数

    UML图

    ★官方PHP高级学习交流社群「点击」管理整理了一些资料,BAT等一线大厂进阶知识体系备好(相关学习资料以及笔面试题)以及不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货

    代码

    • Memento.php
    
    <?php
    
    namespace DesignPatterns\Behavioral\Memento;
    
    class Memento
    {
        /**
         * @var State
         */
        private $state;
    
        /**
         * @param State $stateToSave
         */
        public function __construct(State $stateToSave)
        {
            $this->state = $stateToSave;
        }
    
        /**
         * @return State
         */
        public function getState()
        {
            return $this->state;
        }
    }
    
    • State.php
    
    <?php
    
    namespace DesignPatterns\Behavioral\Memento;
    
    class State
    {
        const STATE_CREATED = 'created';
        const STATE_OPENED = 'opened';
        const STATE_ASSIGNED = 'assigned';
        const STATE_CLOSED = 'closed';
    
        /**
         * @var string
         */
        private $state;
    
        /**
         * @var string[]
         */
        private static $validStates = [
            self::STATE_CREATED,
            self::STATE_OPENED,
            self::STATE_ASSIGNED,
            self::STATE_CLOSED,
        ];
    
        /**
         * @param string $state
         */
        public function __construct(string $state)
        {
            self::ensureIsValidState($state);
    
            $this->state = $state;
        }
    
        private static function ensureIsValidState(string $state)
        {
            if (!in_array($state, self::$validStates)) {
                throw new \InvalidArgumentException('Invalid state given');
            }
        }
    
        public function __toString(): string
        {
            return $this->state;
        }
    }
    
    • Ticket.php
    
    <?php
    
    namespace DesignPatterns\Behavioral\Memento;
    
    /**
     * Ticket 是  Originator  的原始副本
     */
    class Ticket
    {
        /**
         * @var State
         */
        private $currentState;
    
        public function __construct()
        {
            $this->currentState = new State(State::STATE_CREATED);
        }
    
        public function open()
        {
            $this->currentState = new State(State::STATE_OPENED);
        }
    
        public function assign()
        {
            $this->currentState = new State(State::STATE_ASSIGNED);
        }
    
        public function close()
        {
            $this->currentState = new State(State::STATE_CLOSED);
        }
    
        public function saveToMemento(): Memento
        {
            return new Memento(clone $this->currentState);
        }
    
        public function restoreFromMemento(Memento $memento)
        {
            $this->currentState = $memento->getState();
        }
    
        public function getState(): State
        {
            return $this->currentState;
        }
    }
    

    测试

    • Tests/MementoTest.php
    
    <?php
    
    namespace DesignPatterns\Behavioral\Memento\Tests;
    
    use DesignPatterns\Behavioral\Memento\State;
    use DesignPatterns\Behavioral\Memento\Ticket;
    use PHPUnit\Framework\TestCase;
    
    class MementoTest extends TestCase
    {
        public function testOpenTicketAssignAndSetBackToOpen()
        {
            $ticket = new Ticket();
    
            // 打开 ticket
            $ticket->open();
            $openedState = $ticket->getState();
            $this->assertEquals(State::STATE_OPENED, (string) $ticket->getState());
    
            $memento = $ticket->saveToMemento();
    
            // 分配 ticket
            $ticket->assign();
            $this->assertEquals(State::STATE_ASSIGNED, (string) $ticket->getState());
    
            // 现在已经恢复到已打开的状态,但需要验证是否已经克隆了当前状态作为副本
            $ticket->restoreFromMemento($memento);
    
            $this->assertEquals(State::STATE_OPENED, (string) $ticket->getState());
            $this->assertNotSame($openedState, $ticket->getState());
        }
    }
    

    PHP 互联网架构师成长之路*「设计模式」终极指南

    PHP 互联网架构师 50K 成长指南+行业问题解决总纲(持续更新)

    面试10家公司,收获9个offer,2020年PHP 面试问题

    ★如果喜欢我的文章,想与更多资深开发者一起交流学习的话,获取更多大厂面试相关技术咨询和指导,欢迎加入我们的群啊,暗号:phpzh(君羊号码856460874)。

    2020年最新PHP进阶教程,全系列!

    内容不错的话希望大家支持鼓励下点个赞/喜欢,欢迎一起来交流;另外如果有什么问题 建议 想看的内容可以在评论提出

    相关文章

      网友评论

          本文标题:PHP设计模式之备忘录模式(Memento)代码实例大全(25)

          本文链接:https://www.haomeiwen.com/subject/fbyjyktx.html