浅析备忘录模式

在应用程序设计过程中,一些具体操作需要能够支持撤销(undo),例如最近在写的一个文件管理系统。文件的一些基本操作如:rename、copy、cut等,需要支持undo、redo操作来提供更好的用户体验。总所周知,undo、redo操作需要两个模式支撑:备忘录模式(memento)保存对象操作数据状态、命令模式(command)封装用户请求。结合起来可以提供良好的撤销、重做操作。命令模式可以参考上面一篇文章点击打开链接.下面主要说说备忘录模式的实现,如有错误,不令赐教。

备忘录模式主要有3个参与者:

a.保存状态信息的备忘录对象(Memento)

b.产生状态信息的源发器(Originator)

c.备忘录对象的管理器(CareTaker)

源发器提供两个对外的接口:

create_memento(); //保存对象状态信息创建一个备忘录返回
set_memento(Memento $mem); //根据传入的备忘录获取状态信息,恢复状态   

备忘录对象提供两个接口:

    set_state(State $state);    //设备备忘录当前状态
    get_state();                //获取备忘录当前状态

备忘录对象实现:

class Memento {
        private $state;
        public function get_state(){
            return $this->state;
        }
        public function set_state(State $state){
            $this->state = clone $state;
        }
    }

set_state接口通过State参数提示保证参数类型的唯一性。需要注意的是,PHP默认对象赋值的时候不会像C++那般执行拷贝构造函数,PHP基于引用对象计数器,对象赋值默认计数器加一。这里我们使用PHP提供的clone操作保证得到的是一个全新的对象。

源发器实现:

 class Originator{
        private $state;        

        function _construct(){
            $this->state = new State();
            $this->state->set('action', 'create originator');
        }

        function do_action1(){
            $this->state->set('action', 'do_action 1');
        }

        function do_action2(){
            $this->state->set('action', 'do_action 2');
        }

        function create_memento(){
            $mem = new Memento();
            $men->set_state($this->state);
            return $mem;
        }

        function set_memento(Memento $mem){
            $this->state = $mem->get_state();
        }

        function dump(){
            echo $this->state->get('action') . "\n";
        }
    }

状态信息对象:

class State{
        private $values = array();

        public function set($key, $value){
            $this->values[$key] = $value;
        }

        public function get($key){
            if(isset($this->values[$key])){
                return $this->values[$key];
            }
            return null;
        }
    }

最后是备忘录管理器的简单实现:

class CareTaker{
        private $command;

        function __construct($cmd="Originator1"){
            $this->command = $cmd;
        }

        private function do_execute(){
               switch($this->command){
                    case 'Originator1':{
                        $action = new Originator();
                        $mem1 = $action->create_memento();
                        $action->dump();
                        $action->do_action1();
                        $mem2 = $action->create_memento();
                        $action->dump();
                        $action->do_action2();
                        $mem3 = $action->create_memento();
                        $action->dump();
                        //状态恢复
                        $action->set_memento($mem2);
                        $action->dump();
                        $action->set_memento($mem1);
                        $action->dump();
                    }
                }
        }
    }

这里有几个地方可以改进的,首先,管理器应该提供一个队列来管理一系列的备忘录对象。其次客户端请求命令用一个大大的switch-case做分发而不是利用命令模式把请求封装为对象,导致了类结构混乱。下一篇将实现一个完整版本的undo-redo操作。

The end.

时间: 2024-10-09 03:18:00

浅析备忘录模式的相关文章

Java设计模式应用——备忘录模式

备忘录模式主要用于存档.游戏中我们打boss前总会存档,如果打boss失败,则读取存档,重新挑战boss. 可以看出来,备忘录模式一般包括如下数据结构 1. 存档文件:用于恢复备份场景的必要数据: 2. 存档管理器:用于管理存档,包括存档的读写与展示: 3. 被存档的对象. 下面以射击游戏的存档来举例: 1. 射击选手 package com.coshaho.learn.memorandum; // 射击手 public class Shooter { // 血量 private int blo

Java设计模式(十) 备忘录模式 状态模式

(十九)备忘录模式 备忘录模式目的是保存一个对象的某个状态,在适当的时候恢复这个对象. class Memento{ private String value; public Memento(String value){ this.value = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } class Storage

4 行为型模式之- 备忘录模式

备忘录模式介绍: 备忘录模式是一种行为模式,该模式用于保存对象当前的状态,并且在之后可以再次恢复到此状态,这有点像我们平时说的"后悔"药.备忘录模式实现的方式需要保证被保存的对象状态不能被对象从外界访问,目的是为了保护好被保存的这些对象状态的完整性以及内部实现不向外暴露 备忘录模式的定义: 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样,以后就可以将对象恢复到原先的状态 对于备忘录模式来说,比较贴切的场景应该是游戏中的存档功能,该功能就是将游戏进度存储到

备忘录模式

备忘录模式,望文生义就知道它是用来做备忘的,或者可以直接说是“备份”.当需要保存当前状态,以便在不久要恢复此状态时,就可以使用“备忘录模式”.将当前”状态“备份,是不是又new一个类,然后将每个字段方法copy过去就可以了呢?或者说使用我们之前clone方法做深复制浅复制呢?其实不然,在<大话设计模式>中,作者提到了原因,这样会暴露更多的细节给客户端,不符合我们面向对象的思想.什么是暴露更多的细节给客户端?我们来看下面一段代码. 1 package day_27_memento; 2 3 /*

设计模式(12)---备忘录模式

备忘录模式   Memento (行为型模式) 1.概述 备忘录模式:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态. 例如:一些软件提供的撤销功能,游戏的存档读档功能. 2.结构图 3.代码 1 /* 2 * 原发器类 Originator 3 */ 4 public class Role { 5 6 private int level ; 7 private int life ; 8 9 public Role() { 10

备忘录模式(Memento Pattern)

备忘录模式:保存一个对象的某个状态,以便在适当的时候恢复对象. 例子: public class Memento { public String state; public Memento(String state){ this.state = state; } public String getState() { return state; } } public class MementoManager { public List<Memento> list = new ArrayList&

设计模式之备忘录模式

定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样就可以将该对象恢复到原先保存的状态 类图: 结构: 发起人:记录当前时刻的内部状态,负责定义哪些属于备份范围的状态,负责创建和恢复备忘录数据. 备忘录:负责存储发起人对象的内部状态,在需要的时候提供发起人需要的内部状态. 管理角色:对备忘录进行管理,保存和提供备忘录. 优点: 当发起人角色中的状态改变时,有可能这是个错误的改变,我们使用备忘录模式就可以把这个错误的改变还原. 备份的状态是保存在发起人角色之外的,

“备忘录模式”就这么简单

备忘录模式的官方定义: 在不破坏封装性的前提下,获取一个对象的内部状态,并在该对象之外保存这些状态.这样以后就可以通过该对象恢复到原先保存的状态. 大白话说: 一个对象中一般都封装了很多属性,这些属性的值会随着程序的运行而变化.当我们需要保存某一时刻对象的某些值的时候,我们就再创建一个对象,将当前对象中的一些属性保存到新的对象中,当我们需要恢复的时候再从新的对象中取出属性值即可.这种想法就是备忘录模式. 备忘录模式的类图: 1.需要备份的类是Orginator,备份的数据保存在Mementor中

设计模式之行为型模式—— 3.7 备忘录模式

<?php /**  * 3.7 备忘录模式  *  定义:  *  在不破坏封装性的前提下,捕获一个对象的内  *  部状态,并在该对象之外保存这个状态,这样  *  以后就可将该对象恢复到原先保存的状态.  *  * 角色:  *  1. 发起人(Originator)类  *  职责:负责创建一个备忘录Memento,用以  *    记录当前时刻它的内部状态,并可  *    使用备忘录恢复内部状态.Originator  *    可根据需要决定Memento存储它的哪  *    些