>  기사  >  백엔드 개발  >  다시 실행 및 실행 취소의 완벽한 구현

다시 실행 및 실행 취소의 완벽한 구현

WBOY
WBOY원래의
2016-08-08 09:32:36960검색
Undo-redo를 지원하려면 메모 모드와 명령 모드가 필요합니다. 이전에 명령 모드와 메모 모드에 대한 기본 지식을 배웠습니다. 여기서는 두 가지 모드를 결합하여 학습한 지식을 통합하기 위한 실행 취소-다시 실행 작업용 모듈을 구현해야 합니다.

시스템 블록 다이어그램:

네 가지 주요 명령 분배 컨트롤러가 있습니다. 작업:
1. 시스템 초기화, 시스템 구성 매개변수 로드 및 이러한 데이터 캐시 이러한 애플리케이션 수준 구성 매개변수는 직렬화 메커니즘을 사용하여 매번 파일을 읽지 않고도 데이터를 캐시하여 액세스 효율성을 높일 수 있습니다.
2. 프런트엔드 요청을 기반으로 매개변수를 수집하여 요청(Request)을 생성합니다.
3. 요청을 특정 비즈니스 로직의 명령 모듈(Command)에 매핑합니다.
4. 작업을 수행하고 결과를 프런트 엔드 보기로 반환합니다.

비즈니스 로직 계층은 들어오는 컨텍스트 개체를 기반으로 실행 매개변수를 얻을 수 있으며, 실행 후 컨텍스트 개체를 통해 실행 결과를 이전 계층으로 반환할 수 있습니다.

명령 분배 컨트롤러 구현:

class Controller{

	private function __construct() {}

	static function run(){
		$instance = new Controller();
		$instance->init();
		$instance->handleRequest();
	}
	function init(){
		$application
			= \base\ApplicationHelper::instance();
		$application->system_init();
	}
	function handleRequest(){
		$request  = new \controller\Request();
		$cmd_r = new \command\CommandResolver();
		$cmd = $cmd_r->get_command($request);
		$cmd->execute($request);
	}
}
생성자를 비공개로 선언하면 컨트롤러는 싱글톤입니다.

PHP와 같은 해석 언어의 경우 undo/redo 메커니즘을 구현하려면 명령 실행 내역을 저장하기 위해 일부 캐싱 메커니즘(세션)을 사용해야 합니다. 여기서 세션 모듈은 주로 명령 기록 기록을 유지하는 역할을 하며 구현은 다음과 같습니다.

namespace base;

require_once('session_registry.php');

class SessionMementoTaker extends SessionRegistry{
	
	const 	COMMAND_COUNT = 5;
	private $persent = 0;
	private $cmd_stack = array();
	static public function instance(){
		return parent::instance();
	}	

	public function push_command(Command $cmd){
		
		$this->cmd_stack = self::instance()->get('cmd_stack');	
		if(!empty($this->cmd_stack)){
			if(count($this->cmd_stack) >self::COMMAND_COUNT){
				array_shift($this->cmd_stack);
				reset($this->cmd_stack);
			}
		} 
		array_push($this->cmd_stack, $cmd);
		$this->persent = count($this->cmd_stack) + 1;
		self::instance()->set('cmd_stack', $this->cmd_stack);
		self::instance()->set('cmd_persent', $this->persent);
	}	

	public function get_undo_command(){
		$this->persent = self::instance()->get('cmd_persent');	
		$this->cmd_stack = self::instance()->get('cmd_stack');	
		if(!empty($this->cmd_stack) && $this->persent > 0){
			$command = $this->cmd_stack[--$this->persent];
			self::instance()->set('cmd_persent', $this->persent);
			return $command;
		}	
		return null;
	}	
	public function get_redo_command(){
		$this->persent = self::instance()->get('cmd_persent');	
		$this->cmd_stack = self::instance()->get('cmd_stack');	
		if(!empty($this->cmd_stack) && $this->persent < count($this->cmd_stack)){
			$command = $this->cmd_stack[$this->persent++];
			self::instance()->set('cmd_persent', $this->persent);
			return $command;
		}	
		return null;
	}
}

SessionMementoTaker의 구현은 다음을 기반으로 합니다. 이전에 구현된 세션(URL 등록 메커니즘). 쿠키에 저장된 세션 ID를 기반으로 서로 다른 객체 데이터를 복원하면 동일한 사용자가 동일한 객체 데이터에 여러 번 액세스를 요청하는 목적을 달성할 수 있습니다. SessionMementoTaker는 세 가지 추가 인터페이스를 제공합니다. push_command 작업은 기록 명령 목록에 명령을 추가합니다. 히스토리 명령 목록의 최대 길이는 5입니다. 5를 초과하면 첫 번째 명령이 제거됩니다. 또한 push_command는 새 명령을 추가하고 명령 포인터(persent)를 최신 위치로 이동하는 것과 같습니다. 이전 상태를 폐기합니다. get_undo_command는 마지막으로 실행된 기록 명령을 가져오고 포인터를 업데이트합니다. get_redo_command도 마찬가지입니다.
기록 명령 목록: command1---command2---command3---* 별표는 실행될 최신 명령을 가리키는 지속성을 나타냅니다.
실행 취소 작업: command1---command2-*--command3--- 롤백 후 영구 포인터가 뒤로 이동합니다.
실행 취소 작업: command1--*command2----command3--- 롤백 후 영구 포인터가 뒤로 이동합니다.
다시 실행 작업: command1---command2-*--command3--- 다시 실행 후 영구 포인터는 앞으로 이동합니다.
push_command: command1---command2---command3---command4---* persist가 프런트 엔드로 업데이트됩니다.
여기서는 단일 명령 개체를 발신자(Originator)로 간주합니다. 그 순간 내부 상태를 저장하기 위해 필요에 따라 적극적으로 메멘토(memento)를 생성하고, 명령 객체를 이력 명령 기록 목록에 넣는다.

명령 기본 클래스 구현:

namespace woo\command;

require_once('../memento/state.php');
require_once('../memento/memento.php');

abstract class Command {
	
	protected $state;
	final function __construct(){
		$this->state = new \woo\memento\State();
	}
	
	function execute(\woo\controller\Request $request) {
		$this->state->set('request', $request);
		$this->do_execute($request);
	}
	
	abstract function do_execute(\woo\controller\Request $request);
	function do_unexecute(\woo\controller\Request $request) {}
	
	public function get_state(){
		return $this->state;
	}
	
	public function set_state(State $state){
		$this->state = $state;	
	}

	public function get_request(){
		if(isset($this->state)){
			return $this->state->get('request');
		}
		return null;
	}
	
	public function set_request(\woo\controller\Request $request){
		if(isset($this->state)){
			return $this->state->set('request', $request);
		}
	}

	public function create_memento(){
		\woo\base\SessionMementoTaker::push_command($this);
		$mem = new \woo\memento\Memento();
		$mem->set_state($this->state);
        return $mem;
	}

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

명령 작업은 실행 시작 시 요청된 명령의 매개변수를 저장합니다. .실행 중에 필요한 다른 매개변수도 저장할 수 있습니다. 일부 명령은 실행 취소 작업을 지원하지 않으므로 상위 클래스 구현에서는 빈 실행 취소가 사용됩니다. >실행 취소를 지원하는 파일을 복사하는 명령:

명령 개체가 수행하는 작업은 상대적으로 간단합니다. 매개변수(검증 매개변수) 가져오기, 필요한 상태 정보 저장, 제어를 특정 비즈니스 논리 개체로 전송합니다. 실행 결과를 추가하고 반환합니다. 명령마다 다른 요청 매개변수가 필요합니다. 일부 명령에는 실행 취소 작업이 전혀 필요하지 않거나 지원되지 않으므로 create_memento 작업을 선택적으로 수행할 수 있습니다.

class State{
	
	private $values = array();

	function __construct(){
			
	}
	
	public function set($key, $value){
		$this->values[$key] = $value;
	}
	
	public function get($key){
		if(isset($this->values[$key]))
		{
			return $this->values[$key];
		}
		return null;
	}
}
마지막 단계는 undo-redo를 구현하는 것입니다. 여기서는 undo/redo를 컨트롤러에서 추가 배포 처리가 필요 없는 일반적인 명령 요청으로 간주합니다.

실행 취소 명령:

namespace woo\command;

require_once('request.php');
require_once('command.php');
require_once('../base/registry.php');
require_once('../file_manager.php');
require_once('../base/session_memento.php');

class CopyCommand extends Command {
	function do_execute(\controller\Request $request) {
		$src_path = $request->get_property('src');
		$dst_path = $request->get_property('dst');
		$this->state->set('src_path', $src_path);
		$this->state->set('dst_path', $dst_path);
		$this->create_memento();
		$file_manager = \base\Registry::file_manager();
		$ret = $file_manager->copy($src_path, $dst_path);
		$request->add_feedback($ret);
		//...
	}
}

다시 실행 명령:

끝입니다.

namespace woo\command;

require_once('request.php');
require_once('command.php');
require_once('../base/registry.php');
require_once('../base/session_memento.php');

class UndoCommand extends Command{
	public function do_execute(\controller\Request $request){
		$command = \base\SessionMementoTaker::get_undo_command();
		if(isset($command)){
			$old_req = $command->get_request();
			$command->do_unexecute($old_req);
			$request->set_feedback($old_req->get_feedback());
		} else{
			$request->add_feedback('undo command not fount');
		}
		return;
	}
}

위 내용은 관련 내용을 포함하여 redo 및 undo의 전체 구현을 소개합니다. PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.