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):将"请求"(命令/口令)封装 ...
随机推荐
- 大学英语四级之听力Key Words
Key Words关键词 所谓关键词,指的是短文中能够标志着正确答案的词,也就是说,关键词后面往往是正确答案 听力中的关键词可为宏观和微观两方面,一般出现在如下10种位置. 一.宏观方向(主旨大意) ...
- Java入土---基本DOS命令
基本DOS命令 打开cmd方式 开始+系统+命令提示符 win+R,输入cmd 在任意文件夹下,按住shift + 右键,打开命令行窗口 资源管理器里打开 常用DOS命令 盘符切换 E: dir命令查 ...
- dopamine源码解析之dqn_agent
目录 epsilon函数 DQNAgent构造函数核心参数 DQNAgent核心函数 tf.make_template 核心数据流图 epsilon函数 linearly_decaying_epsil ...
- ArcMap操作随记(15)
1.字段顺序的调整 [图层属性]→[字段]([高级排序]功能也在这里) 2.所谓热点地区: 本身是高值,邻居也是高值,才成为热点地区(这是操作中总结出的,但其实了解原理就很简单了,详细请查看空间自相关 ...
- SQL注入及防止SQL注入
•SQL注入 SQL注入是通过操作输入来修改事先定义好的SQL语句,对用户输入的字符串进行过滤,转义,限制或处理不严谨,导致用户可以通过输入精心构造的字符串去非法获取到数据库中的数据,以达到执行代码对 ...
- 如何做一个网站 (C# + MVC Web+ easyUI )
如何做一个网站 小编想做一个网站,采用技术为:C# + MVC Web+ easyUI 小编经过几天的学习,以及指了几位大神指导,初见效果.建立网站的思路:先列举需要用到了几个知识点,然后逐一攻克,然 ...
- vivo 商品中台的可视化微前端实践
一.背景 在电商领域内,商品是一个重要组成部分,与其对应的商品管理系统,则负责商品的新建.编辑.复制等功能.随着商品管理系统的成熟稳定和业务上的扩展需求,催化出了商品中台的诞生.它可以将现有商品功能最 ...
- 简单面试前算法一览java
1.排序 冒泡,快速排序 2.查找 二分查找 3.链表 翻转链表 合并链表 是否有环 b. 快慢指针 public class QuickSort { public static void qui ...
- 什么是springcloud?springcloud断路器的作用是什么?springcloud的核心组件有什么?
一.什么是springcloud 1.springcloud概述 Spring Cloud是一个微服务框架,相比Dubbo等RPC框架, Spring Cloud提供的全套的分布式系统解决方案. Sp ...
- Java并发机制(7)--线程池ThreadPoolExecutor的使用
Java并发编程:线程池的使用整理自:博客园-海子-http://www.cnblogs.com/dolphin0520/p/3932921.html 1.什么是线程池,为什么要使用线程池: 1.1. ...