#组合模式实现简单计算器功能
顶层接口
public interface Expression {
int getValue();
}
存储左右表达式的抽象类
public abstract class BinaryOperatorExpression implements Expression {
Expression left;
Expression right;
protected BinaryOperatorExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
}
加减乘除实现类
public class AddExpression extends BinaryOperatorExpression {
public AddExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public int getValue() {
return left.getValue() + right.getValue();
}
}
public class SubtractExpression extends BinaryOperatorExpression {
public SubtractExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public int getValue() {
return left.getValue() - right.getValue();
}
}
public class MultiplyExpression extends BinaryOperatorExpression {
public MultiplyExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public int getValue() {
return left.getValue() * right.getValue();
}
}
public class DivisionExpression extends BinaryOperatorExpression {
public DivisionExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public int getValue() {
return left.getValue() / right.getValue();
}
}
顶层接口实现类
public class NumberExpression implements Expression {
private final int value;
public NumberExpression(int value) {
this.value = value;
}
@Override
public int getValue() {
return this.value;
}
}
测试类
public class ExpressionParse {
private static final Set<String> OPERATOR = Set.of("+", "-", "*", "/");
public static void main(String[] args) throws IllegalAccessException {
System.out.println(parse("12 + (2 * 3)").getValue());
}
/**
* 将前缀表达式转换为后缀表达式
*
* @param prefixExpression 前缀表达式
* @return 后缀表达式
* @throws IllegalAccessException 非法字符
*/
public static List<String> toSuffixExpression(String prefixExpression) throws IllegalAccessException {
// 后缀表达式
List<String> suffixExpression = new ArrayList<>();
// 辅助栈
Stack<String> symbolStack = new Stack<>();
int point = 0;
while (point < prefixExpression.length()) {
char c = prefixExpression.charAt(point);
switch (c) {
case ' ':
break;
case '(':
symbolStack.push(String.valueOf(c));
break;
case ')':
while (!"(".equals(symbolStack.peek())) {
suffixExpression.add(symbolStack.pop());
}
symbolStack.pop();
break;
case '*':
case '/':
while (!symbolStack.isEmpty() && ("*".equals(symbolStack.peek()) || "/".equals(symbolStack.peek()))) {
suffixExpression.add(symbolStack.pop());
}
symbolStack.push(String.valueOf(c));
break;
case '+':
case '-':
while (topIsOperator(symbolStack)) {
suffixExpression.add(symbolStack.pop());
}
symbolStack.push(String.valueOf(c));
break;
default:
if (Character.isDigit(c)) {
StringBuilder stringBuilder = new StringBuilder();
while (point < prefixExpression.length() && Character.isDigit(prefixExpression.charAt(point))) {
stringBuilder.append(prefixExpression.charAt(point));
point++;
}
point--;
suffixExpression.add(stringBuilder.toString());
} else {
throw new IllegalAccessException("非法字符!");
}
break;
}
point++;
}
while (!symbolStack.isEmpty()) {
suffixExpression.add(symbolStack.pop());
}
return suffixExpression;
}
/**
* 判断栈顶是否为操作符
*
* @param symbolStack 栈
* @return
*/
private static boolean topIsOperator(Stack<String> symbolStack) {
return !symbolStack.isEmpty() && OPERATOR.contains(symbolStack.peek());
}
/**
* 计算结果
*
* @param prefixExpression 前缀表达式
* @return 结果
* @throws IllegalAccessException 非法字符
*/
public static Expression parse(String prefixExpression) throws IllegalAccessException {
List<String> suffixExpression = toSuffixExpression(prefixExpression);
Stack<Expression> stack = new Stack<>();
for (String item : suffixExpression) {
switch (item) {
case "+":
Expression rightAdd = stack.pop();
stack.push(new AddExpression(stack.pop(), rightAdd));
break;
case "-":
Expression rightSubtract = stack.pop();
stack.push(new SubtractExpression(stack.pop(), rightSubtract));
break;
case "*":
Expression rightMultiply = stack.pop();
stack.push(new MultiplyExpression(stack.pop(), rightMultiply));
break;
case "/":
Expression rightDivision = stack.pop();
stack.push(new DivisionExpression(stack.pop(), rightDivision));
break;
default:
int value = Integer.parseInt(item);
stack.push(new NumberExpression(value));
break;
}
}
return stack.pop();
}
}