淺析備忘錄模式

WBOY
發布: 2016-08-08 09:32:39
原創
973 人瀏覽過

      在應用程式設計過程中,一些特定作業需要能夠支援撤銷(undo),例如最近在寫的一個檔案管理系統。文件的一些基本操作如:rename、copy、cut等,需要支援undo、redo操作來提供更好的使用者體驗。總所周知,undo、redo操作需要兩個模式支撐:備忘錄模式(memento)保存物件操作資料狀態、指令模式(command)封裝使用者請求。結合起來可以提供良好的撤銷、重做操作。命令模式可以參考上面一篇文章點擊打開連結.下面主要說說備忘錄模式的實現,如有錯誤,不令賜教。

     備忘錄模式主要有3位參與者:
     a.保存狀態資訊的備忘錄物件(Memento)
     b.產生狀態資訊的來源使用器(Originator) 的管理器
       

源發器提供兩個外部的介面:

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.
    

以上就介紹了淺析備忘錄模式,包含了方面的內容,希望對PHP教學有興趣的朋友有幫助。

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板