初识设计模式——备忘录模式

个人理解

定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

理解:前提条件有两个,一个是不破坏封装性的前提下获取对象的成员属性;另一个是保存获取到的属性。由于PHP主要应用于web端,所以在一次请求中频繁改动某个对象的状态的情况并不常见,所以个人感觉该模式在PHP语言中应用并不广泛。

主要解决:主要解决的是某个或多个状态的保存与恢复问题。

组成部分:Memento(备忘录,负责存储需要保存的状态数据)、Originator(发起人,负责创建并记录一个备忘录Memento)、Caretaker(管理者,负责保存好备忘录Memento,不能对Memento进行操作或检查)。这里在《菜鸟教程》与《大话设计模式》中表述不同,我用的是《大话设计模式》中的表述。注意备忘录有两个接口,Caretaker只能看到窄接口,只能讲Memento传递给其他对象,Originator能够看到一个宽接口,允许它访问返回到先前状态的返回数据。

主要用途:mysql的事物回滚估计使用这个模式做的(个人猜测,没有实际了解过Mysql源码)、文本编辑器的撤销操作等

案例分析

由于本人的经验有限,还真没有在PHP中遇到过这种情况,所以使用的是《大话设计模式》中的单机游戏的例子。

游戏存在一个场景,一个角色存在生命值、攻击力、防御力等属性,在打BOSS的前后状态值不相同(生命值),如果角色与BOSS战斗后不能成功过关(生命值>0),则自动回退到打BOSS之前的状态。

由于打BOSS需要恢复状态,所以需要用到备忘录模式。在本应用场景中,备忘录Memento需要存储角色的三个状态(生命值、攻击力、防御力),发起人Originator用于创建一个Memento对象保存住角色的状态,管理者Caretaker在失败的情况下用于恢复备忘录Memento。

场景代码

角色类(发起者Originator)

replyAttribute($memento);
    }
    //创建一个备忘录对象
    public function buildMemento()
    {
        return (new Memento($this->hp, $this->atk, $this->def));
    }
    //恢复角色的属性值
    public function replyAttribute(Memento $memento)
    {
        $this->hp = $memento->hp;
        $this->atk = $memento->atk;
        $this->def = $memento->def;
    }
    //角色的战斗
    public function combat()
    {
        //角色开始战斗
        echo '角色开始战斗
'; echo '战斗中...
'; //... $this->atk += 80; //角色触发【越战越勇】被动技能 $this->def += 100; //角色触发【坚如磐石】被动技能 //战斗失败 echo '战斗失败
'; $this->hp = 0; return false; } }

备忘录类(Memento)

hp   = $hp;
        $this->atk  = $atk;
        $this->def  = $def;
    }
    public function __get($name)
    {
        switch ($name) {
            case 'hp' :
                return $this->hp;
                break;
            case 'atk' :
                return $this->atk;
                break;
            case 'def' :
                return $this->def;
                break;
            default :
                return null;
                break;
        }
    }
}

管理者(Caretaker)

客户端代码

';
echo '角色非战斗的其他动作...
'; echo '生成备份文件'; //生成备份文件 Caretaker::setMemento($role->buildMemento()); var_dump(Caretaker::getMemento()); echo '
'; //角色开始战斗 $role->combat(); echo '当前角色状态';var_dump($role); echo '
'; //从备忘录中恢复 echo '从备忘录中恢复
'; $role->replyAttribute(Caretaker::getMemento()); echo '当前角色状态';var_dump($role);

UML图

初识设计模式——备忘录模式_第1张图片

总结

备忘录模式适用于功能比较复杂,但需要记录并恢复到之前的状态下。适用备忘录模式会导致内存损耗严重,所以请谨慎适用。

参考信息

《菜鸟教程——备忘录模式》http://www.runoob.com/design-pattern/memento-pattern.html

《大话设计模式》

下一篇

初识设计模式——组合模式

你可能感兴趣的:(设计模式)