Java/C++实现命令模式---多次撤销和撤回
某系统需要提供一个命令集合(注:可以使用链表,栈等集合对象实现),用于存储一系列命令对象,并通过该命令集合实现多次undo()和redo()操作,可以使用加法运算来模拟实现。\
类图:

Java代码:
package Lab16;
import java.util.Stack; public abstract class AbstractCommand {
public abstract int execute(int value);
public abstract int undo();
public abstract int redo();
} public class AddCommand extends AbstractCommand {
private Adder adder = new Adder();
private Stack<Integer> unStack = new Stack<Integer>();// 返回栈,用来记录所做的每一步操作,用于撤回
private Stack<Integer> reStack = new Stack<Integer>();// 重复栈,用来存储返回栈弹出的数据,由于重复
/**
* 撤回
*
*/
public int undo() {
int i=0;
if (unStack.isEmpty()) { i=-1;
}else{
Integer pop = unStack.pop();
reStack.push(pop);
if(!unStack.isEmpty()){//判断弹出数据后是否为空,如果为空,说明已撤回到最原始状态
i=unStack.peek();
}
}
return i;
} /**
* 恢复
*/
public int redo() {
int i=0;
if (reStack.isEmpty()) {
i=-1;
}else{//撤回时只要可以可以撤回,则返回栈一定有数据
Integer pop = reStack.pop();
unStack.push(pop);
i=pop;
}
return i;
} /**
* 执行计算,并进行栈的更新
*/
public int execute(int value) {
int v = 0;
if (unStack.isEmpty()) {// 说明还没有数据
v = adder.add(value);
unStack.push(v);
} else {// 需要更新两个栈中的内容,并计算结果,其中返回栈应该更新,重复栈应该清空
v = adder.add(value);
unStack.push(v);
if (!reStack.isEmpty()) {
for (int i = 0; i < reStack.size(); i++) {
reStack.pop();
}
}
}
return v;
}
} public class Adder {
private int num =0;
public int add(int value) {
num+=value;
return num;
}
} public class CalculatorForm {
private AbstractCommand command;
public void setCommand(AbstractCommand command) {
this.command =command;
}
/**
* 执行运算
* @param value
*/
public void compute(int value) {
command.execute(value);
}
/**
* 撤回
*/
public void undo() {
int i = command.undo();
if(i==-1){
System.out.println("缓存中已不存在数据");
}else{
System.out.println("执行成功,运算结果是:"+i);
}
}
/**
* 恢复
*/
public void redo() {
int i = command.redo();
if(i==-1){
System.out.println("已恢复至最新数据");
}
else{
System.out.println("执行成功,运算结果是:"+i);
}
}
} public class Client {
public static void main(String[] args) {
CalculatorForm form = new CalculatorForm();
AddCommand command = new AddCommand();
form.setCommand(command);
//计算
System.out.println("------计算过程------");
form.compute(1);
form.compute(2);
form.compute(3);
form.compute(4);
//多次撤回
System.out.println("------撤回过程------");
form.undo();
form.undo();
form.undo();
form.undo();
form.undo();
//多次恢复
System.out.println("------恢复过程------");
form.redo();
form.redo();
form.redo();
form.redo();
form.redo();
}
}
C++代码:
#include<iostream>
#include<stack>
using namespace std;
int num=0;
class AbstractCommand {
public:
virtual int execute(int value)=0;
virtual int undo()=0;
virtual int redo()=0;
};
class Adder { public:
int add(int value) {
num+=value;
return num;
}
};
class AddCommand :public AbstractCommand {
private:
Adder *adder;
stack<int> unStack;
stack<int> reStack;
public:
int undo() {
//adder= new Adder();
int i=0;
if (unStack.empty()) {
i=-1;
}else{
int pop = unStack.top();
reStack.push(pop);
unStack.pop();
if(!unStack.empty()){//判断弹出数据后是否为空,如果为空,说明已撤回到最原始状态
i=unStack.top();
}
} return i;
}
int redo() {
//adder= new Adder();
int i=0;
if (reStack.empty()) {
i=-1;
}else{//撤回时只要可以可以撤回,则返回栈一定有数据
// reStack.pop(); int pop = reStack.top();
reStack.pop();
unStack.push(pop);
i=pop; }
return i;
}
int execute(int value) { int v = 0;
if (unStack.empty()) {// 说明还没有数据
v = adder->add(value);
unStack.push(v);
} else {// 需要更新两个栈中的内容,并计算结果,其中返回栈应该更新,重复栈应该清空
v = adder->add(value);
unStack.push(v);
if (!reStack.empty()) {
for (int i = 0; i < reStack.size(); i++) {
// reStack.top();
//reStack.pop();
}
}
}
return v;
}
};
class CalculatorForm {
private:
AbstractCommand *command;
public:
void setCommand(AbstractCommand *command) {
this->command =command;
}
void compute(int value) {
command->execute(value);
}
void undo() {
int i = command->undo();
if(i==-1){
cout<<"缓存中已不存在数据"<<endl;
}else{
cout<<"执行成功,运算结果是:"<<i<<endl;
}
}
void redo() {
int i = command->redo();
if(i==-1){
cout<<"已恢复至最新数据"<<endl;
}
else{
cout<<"执行成功,运算结果是:"<<i<<endl;
}
}
};
int main(){
CalculatorForm *form = new CalculatorForm();
AddCommand *command = new AddCommand();
form->setCommand(command);
//计算
cout<<"------计算过程------"<<endl;
form->compute(1);
form->compute(2);
form->compute(3);
form->compute(4);
//多次撤回
cout<<"------撤回过程------"<<endl;
form->undo();
form->undo();
form->undo();
form->undo();
form->undo();
//多次恢复
cout<<"------恢复过程------"<<endl;
form->redo();
form->redo();
form->redo();
form->redo();
form->redo();
return 0;
}
运行截图:


Java/C++实现命令模式---多次撤销和撤回的更多相关文章
- 折腾Java设计模式之命令模式
博客原文地址 折腾Java设计模式之命令模式 命令模式 wiki上的描述 Encapsulate a request as an object, thereby allowing for the pa ...
- 设计模式 - 命令模式(command pattern) 撤销(undo) 具体解释
命令模式(command pattern) 撤销(undo) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 參考命令模式: http://blog.cs ...
- Java设计模式 之 命令模式
1 从属模式分类 行为性模式 2 命令模式意图 命令模式可将动作的请求者和动作的执行者对象中解耦. 该模式将一个行为操作发起者的请求封装到对象中,该请求由另外一个对象执行. 将动作 ...
- JAVA设计模式之 命令模式【Command Pattern】
一.概述 命令模式能够将请求发送者和接收者全然解耦.发送者与接收者之间没有直接引用关系,发送请求的对象仅仅须要知道怎样发送请求,而不必知道怎样完毕请求.核心在于引入了命令类,通过命令类来减少发送者和接 ...
- java设计模式之命令模式以及在java中作用
命令模式属于对象的行为模式.命令模式又称为行动(Action)模式或交易(Transaction)模式. 命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化,对请 ...
- 14.java设计模式之命令模式
基本需求: 一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装app就可以控制对这些家电工作 这些智能家电来自不同的厂家,我们不想针对每一种家电都安装一个App分别控制,我们希望只要一个 ...
- 玉帝传美猴王上天,大闹天宫之Java设计模式:命令模式
目录 示例 改进代码 命令模式 定义 意图 主要解决问题 何时使用 优缺点 玉帝传美猴王上天 命令模式和策略模式的区别 示例 系统需要设计一个命令行界面,用户可输入命令来执行某项功能,系统的功能会不断 ...
- java设计模式之命令模式
学校中.生活中.社会中总是会存在一定的阶层,虽然我们很多人都不可认可阶层的存在.命令这一词也就在阶层中诞生.家长命令孩子,老师命令学生,领导命令小娄娄.这些都在我们的生活存在的东西,相信这一个模式学习 ...
- Java设计模式菜鸟系列(七)命令模式建模与实现
转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/39804057 命令模式(Command):将"请求"(命令/口令)封装 ...
随机推荐
- C#控制打印机打印
一.引用BarcodeStandard.dll #region BarcodeStandard.dll /* * * 使用说明 需要通过NuGet进行安装BarcodeLib.dll,必不可少 */ ...
- mysql 创建临时表
创建临时表 create TEMPORARY table SalesSummary( product_name VARCHAR(50) NOT NULL, total_sales DECIMAL( ...
- Sobel算子 Scharr算子 Laplacian算子
图像梯度处理 Sobel算子 水平方向: 对于线条A和线条B,右侧像素值与左侧像素值的差值不为零,因此是边界 上下像素值差值为0,左右素值的差值不为零,分布为正负, 离的近的为2,离的远的为1 P5= ...
- Linux系统常用指令
建立一个文件或文件夹的软链接: ln -s 原名 软链接名 软链接就类似Windows下的"快捷方式",访问它其实访问的是它指向的内容. git仓库操作 1.通常远程操作的第一步, ...
- dotnet 6 使用 string.Create 提升字符串创建和拼接性能
本文告诉大家,在 dotnet 6 或更高版本的 dotnet 里,如何使用 string.Create 提升字符串创建和拼接的性能,减少拼接字符串时,需要额外申请的内存,从而减少内存回收压力 本文也 ...
- 洛谷P1091 [NOIP2004 提高组] 合唱队形
本题是一个简单的 LIS(最长上升子序列)问题 只是要求俩次最长上子序列而已 很容易的 首先由于是最长上升子序列 所以朴素法的动态规划表达式为 f[i] = max( f[i] , f[ ...
- 《HelloGitHub》第 72 期
兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweiha ...
- 使用过滤器获取系统目录或文件名(java.io)
import java.io.File;import java.io.FilenameFilter; File[] file = new File("D:\\"); //使用Fil ...
- 构造器(constructor)是否可被重写(override)?
构造器不能被继承,因此不能被重写,但可以被重载.
- Oracle入门基础(一)一一基本查询
SQL> --当前用户 SQL> show user SQL> --当前用户下的表 SQL> select * from tab; TNAME TABTYPE CLUSTERI ...