시스템 블록 다이어그램:
네 가지 주요 명령 분배 컨트롤러가 있습니다. 작업:
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; } }
명령 기본 클래스 구현:
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; } }