前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >php设计模式(二十一):备忘录模式(Memento)

php设计模式(二十一):备忘录模式(Memento)

作者头像
陈大剩博客
发布2023-05-24 14:28:24
2450
发布2023-05-24 14:28:24
举报

备忘录模式

备忘录模式又称为快照、Snapshot、Memento,备忘录模式是一种行为设计模式,允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。

问题

很多时候我们是按照产品的需求,对代码多次改版,可能因为某次疏忽(未保存就关机了),就导致代码不翼而飞,这会使我们非常懊恼,少则加班几小时,多则几个通宵。如果有”后悔药”可吃,那一定不会说:“曾经有一份写好的代码摆在我的面前我没有好好去保存,等我失去的时候才追悔莫及,人间最痛苦的事莫过于此,如果上天能给我一次再来一次的机会,我一定狂按 Ctrl + s”。

上述情况非常常见,而不常见的却是没有“后悔药”可吃。那我们在编程中有没有“后悔药”呢?如开发一款游戏,我们打 BOSS 失败之后,想要吃“后悔药”回到打 BOSS 之前的状态。

解决方法

在编程中我们通过一个备忘录类(Memento)专门存储对象状态,我们可以提供历史类(History)存储大量的备忘录对象,当用户类触发撤销操作时,历史类将从栈中取回最近的备忘录,并将其传递给使用类以请求进行回滚。

也就是说我们打 BOSS 之前我们保存一个状态,我们打 BOSS 失败之后,使用备忘录类回滚到 BOSS 之前的状态。

结构

Origin:原型类 需要创建快照的类 Snapshot:快照类 存原型快照的地方 History:历史类 存储的多个快照 以便能回滚和撤销

代码示例

原型类

代码语言:javascript
复制
/**
 * 原型类
 */
class Origin
{

    /**
     * 血量值
     * @var
     */
    private $hp;

    /**
     * 体力值
     * @var
     */
    private $lp;

    /**
     * 力量
     * @var
     */
    private $power;

    public function __construct()
    {
        // 初始化时 HP:100、LP:100、power:50
        $this->hp = 100;
        $this->lp = 100;
        $this->power = 50;
    }

    /**
     * 设置 HP
     * @param $hp
     * @return void
     * @author chendashengpc
     */
    public function setHp($hp)
    {
        $this->hp = $hp;
    }

    /**
     * 设置 LP
     * @param $lp
     * @return void
     * @author chendashengpc
     */
    public function setLp($lp)
    {
        $this->lp = $lp;
    }

    /**
     * 设置 Power
     * @param $power
     * @return void
     * @author chendashengpc
     */
    public function setPower($power)
    {
        $this->power = $power;
    }

    /**
     * 制作备份
     * @return void
     * @author chendashengpc
     */
    public function makeSnapshot()
    {
        return new Snapshot($this->hp, $this->lp, $this->power);
    }

    /**
     * 回滚备份
     * @return void
     * @author chendashengpc
     */
    public function restore(Snapshot $snapshot)
    {
        $this->hp = $snapshot->getHp();
        $this->lp = $snapshot->getLp();
        $this->power = $snapshot->getPower();
    }

    /**
     * 魔术方法设置字符串
     * @return string
     * @author chendashengpc
     */
    public function __toString()
    {
        return 'HP:' . $this->hp . PHP_EOL . 'LP:' . $this->lp . PHP_EOL . 'POWERL:' . $this->power . PHP_EOL;
    }
}

快照类

代码语言:javascript
复制
/**
 * 快照
 */
class Snapshot
{

    /**
     * 血量值
     * @var
     */
    private $hp;

    /**
     * 体力值
     * @var
     */
    private $lp;

    /**
     * 力量
     * @var
     */
    private $power;

    /**
     * 初始化备忘录
     * @param $hp
     * @param $lp
     * @param $power
     */
    public function __construct($hp, $lp, $power)
    {
        $this->hp = $hp;
        $this->lp = $lp;
        $this->power = $power;
    }

    /**
     * 获取备忘录HP
     * @return mixed
     * @author chendashengpc
     */
    public function getHp()
    {
        return $this->hp;
    }

    /**
     * 获取备忘录LP
     * @return mixed
     * @author chendashengpc
     */
    public function getLp()
    {
        return $this->hp;
    }
    /**
     * 获取备忘录POWER
     * @return mixed
     * @author chendashengpc
     */
    public function getPower()
    {
        return $this->power;
    }

}

历史类

代码语言:javascript
复制
/**
 * 存历史类
 */
class History
{
    public $list = [

    ];

    /**
     * 设置快照
     * @param Snapshot $snapshot
     * @return void
     * @author chendashengpc
     */
    public function makeBackup(Snapshot $snapshot)
    {
        $this->list[] = $snapshot;
    }

    /**
     * 返回备忘录
     * @return mixed|null
     * @author chendashengpc
     */
    public function undo()
    {
        if (count($this->list)) {
            $snapshot = array_pop($this->list);
            return $snapshot;
        }
        return null;
    }

}

客户端使用

代码语言:javascript
复制
/**
 * 初始化
 */
$origin = new Origin();
echo $origin . PHP_EOL;
/**
 * 提升力量
 */
$origin->setHp(200);
$origin->setLp(200);;
$origin->setPower(100);
echo $origin . PHP_EOL;

/**
 * 存进版本库
 */
$history = new History();
/**
 * 设置快照
 */
$history->makeBackup($origin->makeSnapshot());

$origin->setHp(120);
$origin->setLp(120);;
$origin->setPower(60);
echo $origin . PHP_EOL;
/**
 * 回滚
 */
$snapshot = $history->undo();
$origin->restore($snapshot);
echo $origin . PHP_EOL;

输出

代码语言:javascript
复制
HP:100
LP:100
POWERL:50

HP:200
LP:200
POWERL:100

HP:120
LP:120
POWERL:60

HP:200
LP:200
POWERL:100

UML

UML
UML

优缺点

优点

  • 可以在不破坏对象封装情况的前提下创建对象状态快照。
  • 可以通过让负责人维护原发器状态历史记录来简化原发器代码。

缺点

  • 如果客户端过于频繁地创建备忘录, 程序将消耗大量内存。
  • 负责人必须完整跟踪原发器的生命周期, 这样才能销毁弃用的备忘录。
  • 绝大部分动态编程语言 (例如 PHP、 Python 和 JavaScript)不能确保备忘录中的状态不被修改。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-05-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 备忘录模式
  • 问题
  • 解决方法
  • 结构
  • 代码示例
    • 原型类
      • 快照类
        • 历史类
          • 客户端使用
          • UML
          • 优缺点
            • 优点
              • 缺点
              相关产品与服务
              对象存储
              对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档