欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用命令模式实现简单的支持撤销的计算器

程序员文章站 2022-03-10 19:11:02
...

1.支持的操作符有"+", "-", "*", "/"

2.撤销符号为"<"

3.例如输入"1", "+", "2", "<", "+", "1", "<", "+", "3",输出计算结果4

4.例如输入"100", "/", "2", "<", "+", "5", "<", "*", "4", “+", "1", "-", "10", "<", "<",输出计算结果400


要求:1)使用TDD

2)使用命令模式


5.简单类图设计

使用命令模式实现简单的支持撤销的计算器

6.单元测试

package com.pattern.command;

import junit.framework.Assert;

import org.junit.Test;

import com.pattern.command.undocalc.UndoCalc;

public class UndoCalcTest {
	@Test
	public void testInit() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("1");
		Assert.assertEquals("1", ret);
	}

	@Test
	public void testAddCmd1() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("1", "+", "2", "<", "+", "1", "<", "+", "3");
		Assert.assertEquals("4", ret);
	}

	@Test
	public void testAddCmd2() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("1", "+", "2", "+", "1", "<", "+", "3");
		Assert.assertEquals("6", ret);
	}

	@Test
	public void testAddCmd3() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("1", "+", "2", "+", "1", "+", "3");
		Assert.assertEquals("7", ret);
	}

	@Test
	public void testAddCmd4() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("1", "+", "2", "+", "1", "+", "3", "<", "<");
		Assert.assertEquals("3", ret);
	}

	@Test
	public void testSubCmd1() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("1", "-", "2", "<", "-", "1", "<", "-", "3");
		Assert.assertEquals("-2", ret);
	}

	@Test
	public void testSubCmd2() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("1", "-", "2", "-", "1", "<", "-", "3");
		Assert.assertEquals("-4", ret);
	}

	@Test
	public void testAddSubCmd() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("1", "+", "2", "-", "1", "<", "-", "3");
		Assert.assertEquals("0", ret);
	}

	@Test
	public void testMulCmd() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("2", "*", "2", "<", "*", "3", "<", "*", "6");
		Assert.assertEquals("12", ret);
	}

	@Test
	public void testDevCmd() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("100", "/", "2", "<", "/", "5", "<", "/", "4");
		Assert.assertEquals("25", ret);
	}

	@Test
	public void testAllCmd() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("100", "/", "2", "<", "+", "5", "<", "*", "4",
				"+", "1", "-", "10", "<", "<");
		Assert.assertEquals("400", ret);
	}

	@Test
	public void testExceptionCmd() {
		UndoCalc calc = new UndoCalc();
		String ret = calc.calc("100", "<", "<");
		Assert.assertEquals("ERROR INPUT", ret);
	}

}


7.源码

package com.pattern.command.undocalc;

import java.util.Arrays;
import java.util.List;

import net.mindview.util.Stack;

public class UndoCalc {
	int result;

	public String calc(String... cmd) {
		try {
			result = Integer.valueOf(cmd[0]);
			for (int i = 1; i < cmd.length; ++i) {
				String c = cmd[i];
				if (isOperator(c)) {
					Operator op = getNewOperator(c);
					String nextC = cmd[++i];
					result = op.calc(result, Integer.valueOf(nextC));
					pushOp((Undoable) op);
				} else if (isUndo(c)) {
					Undoable op = popOp();
					result = op.undo();
				}
			}
			return String.valueOf(result);
		} catch (Exception e) {
			return "ERROR INPUT";
		}
	}

	private Stack<Undoable> opStack = new Stack<Undoable>();

	private Undoable popOp() {
		return opStack.pop();
	}

	private void pushOp(Undoable op) {
		opStack.push(op);
	}

	private boolean isUndo(String c) {
		return "<".equals(c);
	}

	private Operator getNewOperator(String c) {
		if ("+".equals(c)) {
			return new UndoAddOperator();
		} else if ("-".equals(c)) {
			return new UndoSubOperator();
		} else if ("*".equals(c)) {
			return new UndoMulOperator();
		} else if ("/".equals(c)) {
			return new UndoDevOperator();
		}
		return null;
	}

	private static String[] ops = new String[] { "+", "-", "*", "/" };
	private static List<String> opList = Arrays.asList(ops);

	private boolean isOperator(String c) {
		return opList.contains(c);
	}
}

package com.pattern.command.undocalc;

public interface Undoable {
	int undo();
}

package com.pattern.command.undocalc;

public interface Operator {

	int calc(int result, Integer second);

}

package com.pattern.command.undocalc;

public abstract class UndoableOperator implements Undoable {

	int backUp;

	protected void backUpForUndo(int result) {
		backUp = result;
	}

	@Override
	public int undo() {
		return backUp;
	}

}

package com.pattern.command.undocalc;

public class AddOperator implements Operator {

	@Override
	public int calc(int result, Integer second) {
		return result + second;
	}

}

package com.pattern.command.undocalc;

public class DevOperator implements Operator {

	@Override
	public int calc(int result, Integer second) {
		return result / second;
	}

}

package com.pattern.command.undocalc;

public class MulOperator implements Operator {

	@Override
	public int calc(int result, Integer second) {
		return result * second;
	}

}

package com.pattern.command.undocalc;

public class SubOperator implements Operator {

	@Override
	public int calc(int result, Integer second) {
		return result - second;
	}

}

package com.pattern.command.undocalc;

public class UndoAddOperator extends UndoableOperator implements Operator {
	Operator op = new AddOperator();

	@Override
	public int calc(int result, Integer valueOf) {
		backUpForUndo(result);
		return op.calc(result, valueOf);
	}

}

package com.pattern.command.undocalc;

public class UndoDevOperator extends UndoableOperator implements Operator {
	Operator op = new DevOperator();

	@Override
	public int calc(int result, Integer valueOf) {
		backUpForUndo(result);
		return op.calc(result, valueOf);
	}

}

package com.pattern.command.undocalc;

public class UndoMulOperator extends UndoableOperator implements Operator {
	Operator op = new MulOperator();

	@Override
	public int calc(int result, Integer valueOf) {
		backUpForUndo(result);
		return op.calc(result, valueOf);
	}

}

package com.pattern.command.undocalc;

public class UndoSubOperator extends UndoableOperator implements Operator {
	Operator op = new SubOperator();

	@Override
	public int calc(int result, Integer valueOf) {
		backUpForUndo(result);
		return op.calc(result, valueOf);
	}

}

package com.pattern.command.undocalc;

public interface OperatorFactory {
	Operator getOperator(String operator);
}



package com.pattern.command.undocalc;

public class NoramlOperatorFactory implements OperatorFactory {

	@Override
	public Operator getOperator(String operator) {
		if ("+".equals(operator)) {
			return new AddOperator();
		} else if ("-".equals(operator)) {
			return new SubOperator();
		} else if ("*".equals(operator)) {
			return new MulOperator();
		} else if ("/".equals(operator)) {
			return new DevOperator();
		}
		return null;
	}

}



package com.pattern.command.undocalc;

public class UndoOperatorFactory implements OperatorFactory{

	@Override
	public Operator getOperator(String operator) {
		if ("+".equals(operator)) {
			return new UndoAddOperator();
		} else if ("-".equals(operator)) {
			return new UndoSubOperator();
		} else if ("*".equals(operator)) {
			return new UndoMulOperator();
		} else if ("/".equals(operator)) {
			return new UndoDevOperator();
		}
		return null;
	}

}