如何优化Android Studio中Java代码的复杂分支逻辑?
计算器代码优化方案
你的代码目前存在逻辑过于集中、重复代码冗余、可读性差的问题,下面是几个落地性强的优化方向:
1. 用枚举替代字符串常量,消除硬编码
原代码直接用字符串判断按钮类型,容易出错且难以维护。定义一个枚举类封装所有按钮的类型和文本:
public enum CalculatorButton { CLEAR("AC"), DELETE("⌫"), EQUALS("="), BRACKET("( )"), SQUARE_ROOT("√"), LOG("log"), TAN("tan"), COS("cos"), SIN("sin"), PERCENT("%"), FACTORIAL("!"), POWER("^"), MINUS("-"), PLUS("+"), MULTIPLY("×"), DIVIDE("÷"), PI("π"), DOT("."), NUMBER(null); // 数字按钮统一归类 private final String text; CalculatorButton(String text) { this.text = text; } public static CalculatorButton fromText(String text) { for (CalculatorButton button : values()) { if (text.equals(button.text)) { return button; } } // 数字按钮返回NUMBER类型 if (text.matches("[0-9]")) { return NUMBER; } throw new IllegalArgumentException("Unknown button text: " + text); } }
这样switch时直接用枚举,避免字符串拼写错误:
CalculatorButton button = CalculatorButton.fromText(buttonString); switch (button) { case CLEAR: clearMethod(); break; case DELETE: deleteMethod(); break; case BRACKET: handleBracketInput(); // 拆分到独立方法 break; // ... 其他case }
2. 拆分巨型case到独立方法
原代码中( )和.的逻辑过于冗长,把这些逻辑拆成单独的方法,让switch结构更清晰:
private void handleBracketInput() { if (mInputText.length() == 0) { addLeftBracket(); return; } if (mCursorPosition == mInputText.length()) { handleBracketAtEnd(); } else if (mCursorPosition == 0) { handleBracketAtStart(); } else { handleBracketInMiddle(); } } // 再拆分更细的子方法 private void addLeftBracket() { updateInputView(mCursorPosition + 1, mCursorPosition, getResources().getString(R.string.bracketleft)); mBracketStatus++; } private void handleBracketAtEnd() { if (mBracketStatus > 0) { char lastChar = mInputText.charAt(mCursorPosition - 1); if (isValidBeforeRightBracket(lastChar)) { addRightBracket(); } else if (isValidBeforeLeftBracket(lastChar)) { addLeftBracket(); } } else { char lastChar = mInputText.charAt(mCursorPosition - 1); if (isValidBeforeLeftBracket(lastChar)) { addLeftBracket(); } } }
3. 用集合替代字符串查找,提升可读性和性能
原代码用NOT_BEFORE_BRACKET_LEFT.indexOf(...) == -1这种方式判断字符合法性,可读性差且性能低。改成用Set<Character>存储允许/禁止的字符:
// 类初始化时定义集合 private static final Set<Character> BEFORE_LEFT_BRACKET_FORBIDDEN = new HashSet<>(Arrays.asList('.', 'a', 'n', 'o', 't', 'c', 's', 'i', 'l', 'g')); private static final Set<Character> BEFORE_RIGHT_BRACKET_FORBIDDEN = new HashSet<>(Arrays.asList('.', 'a', 'n', 'o', 't', 'c', 's', 'i', 'l', 'g')); // 判断方法 private boolean isValidBeforeLeftBracket(char c) { return !BEFORE_LEFT_BRACKET_FORBIDDEN.contains(c); } private boolean isValidBeforeRightBracket(char c) { return !BEFORE_RIGHT_BRACKET_FORBIDDEN.contains(c); }
这样代码里的判断逻辑就变成if (isValidBeforeRightBracket(lastChar)),可读性大幅提升。
4. 提取重复逻辑为公共方法
原代码中很多按钮的输入判断逻辑重复(比如判断光标在开头、结尾、中间的情况),提取成公共方法:
// 判断是否可以在当前光标位置插入内容 private boolean canInsertAtCurrentPosition(Set<Character> forbiddenBefore, Set<Character> forbiddenAfter) { if (mInputText.length() == 0) { return true; } if (mCursorPosition == mInputText.length()) { char lastChar = mInputText.charAt(mCursorPosition - 1); return !forbiddenBefore.contains(lastChar); } else if (mCursorPosition == 0) { char firstChar = mInputText.charAt(0); return !forbiddenAfter.contains(firstChar); } else { char beforeChar = mInputText.charAt(mCursorPosition - 1); char afterChar = mInputText.charAt(mCursorPosition); return !forbiddenBefore.contains(beforeChar) && !forbiddenAfter.contains(afterChar); } }
然后像√按钮的逻辑就可以简化为:
case SQUARE_ROOT: Set<Character> sqrtForbiddenBefore = Collections.singleton('.'); if (canInsertAtCurrentPosition(sqrtForbiddenBefore, NOT_AFTER_OPERATOR_1_SET)) { updateInputView(mCursorPosition + 1, mCursorPosition, button.getText()); } break;
5. 封装输入状态,避免散列变量
把mInputText、mCursorPosition、mBracketStatus这些状态封装成一个单独的类,比如CalculatorInputState,让状态管理更集中:
public class CalculatorInputState { private StringBuilder inputText; private int cursorPosition; private int bracketStatus; public CalculatorInputState() { inputText = new StringBuilder(); cursorPosition = 0; bracketStatus = 0; } // 提供getter和setter,以及操作方法 public void addText(String text) { inputText.insert(cursorPosition, text); cursorPosition += text.length(); } public char getCharBeforeCursor() { if (cursorPosition == 0) { throw new IllegalStateException("Cursor at start, no character before"); } return inputText.charAt(cursorPosition - 1); } // ... 其他必要的方法 }
这样原代码里的状态操作就变成调用这个类的方法,减少散列变量带来的维护成本。
进阶:用策略模式彻底消除switch
如果想进一步解耦,可以给枚举添加一个处理接口,每个枚举实现自己的处理逻辑:
public interface ButtonHandler { void handle(CalculatorInputState state, CalculatorView view); } public enum CalculatorButton implements ButtonHandler { CLEAR("AC") { @Override public void handle(CalculatorInputState state, CalculatorView view) { view.clear(); state.reset(); } }, BRACKET("( )") { @Override public void handle(CalculatorInputState state, CalculatorView view) { // 括号处理逻辑 } }, // ... 其他枚举实现handle方法 };
然后调用时直接:
CalculatorButton button = CalculatorButton.fromText(buttonString); button.handle(mInputState, mCalculatorView);
这样就彻底去掉了巨型switch,代码结构更清晰,扩展新按钮时只需添加枚举即可。
内容的提问来源于stack exchange,提问作者tenzinjamyangzhs
相关产品推荐
相关产品推荐

