如何将静态方法与变量重构为面向对象的实例化设计

本文讲解如何将 java 中过度依赖 static 的矩阵填充程序改造为符合面向对象原则的实例化结构,通过移除 static 修饰符、引入构造与实例方法,提升代码可维护性与可测试性。

在原始代码中,所有字段(如 matrix、rows、cols、enemy、target)和方法(如 matrixCreator、recursive、valid、printer)均被声明为 static,导致整个逻辑强耦合于类本身,丧失了面向对象的核心优势:封装、实例独立性与可重用性。例如,若需同时处理多个不同矩阵(如多组测试用例),静态设计将因共享状态而相互干扰。

要正确重构,核心原则是:将数据与行为绑定到对象实例上。具体步骤如下:

  1. 移除所有 static 修饰符(字段与方法);
  2. 在 main 中创建类的实例,而非直接调用静态成员;
  3. 将原 main 中的业务逻辑提取为一个非静态的入口方法(如 run() 或 start()),由实例调用;
  4. 确保所有字段在实例方法中通过 this 隐式访问(无需显式前缀)。

以下是重构后的完整示例(关键改动已加注释):

public class MatrixRefill {
    // ✅ 移除 static:变为实例字段
    private String[][] matrix;
    private int rows;
    private int cols;
    private String enemy;
    private String target;

    public static void main(String[] args) {
        // ✅ 在 main 中创建实例,并委托执行
        MatrixRefill app = new MatrixRefill();
        app.run(args); // 调用实例方法
    }

    // ✅ 非静态入口方法,接收参数并驱动流程
    public void run(String[] args) {
        if (args.length < 3) {
            throw new IllegalArgumentException("Usage:   ");
        }
        target = args[2];
        // 解析位置:如 "2,1" → row=2, col=1
        String[] pos = args[1].split(",");
        rows = Integer.parseInt(pos[0].trim());
        cols = Integer.parseInt(pos[1].trim());

        matrix = matrixCreator(args[0]);
        enemy = matrix[rows][cols];
        recursive(rows, cols, target);
        printer(matrix);
    }

    // ✅ 所有辅助方法均改为实例方法(无 static)
    public String[][] matrixCreator(String mx) {
        int ro = 0, co = 0;
        for (int i = 0; i < mx.length(); i++) {
            if (mx.charAt(i) == ',') co++;
            else if (mx.charAt(i) == '-') ro++;
        }
        String[][] matriks = new String[ro + 1][co / 3 + 1]; // 注意:此解析逻辑需与输入格式严格匹配

        ro = 0; co = 0;
        for (int j = 0; j < mx.length(); j++) {
            char c = mx.charAt(j);
            if (c == ',') co++;
            else if (c == '-') {
                ro++; co = 0;
            } else if (Character.isLetter(c)) {
                matriks[ro][co] = String.valueOf(c);
            }
        }
        return matriks;
    }

    public void recursive(int row, int col, String target) {
        if (valid(row, col)) {
            matrix[row][col] = target;
            recursive(row + 1, col, target);
            recursive(row - 1, col, target);
            recursive(row, col + 1, target);
            recursive(row, col - 1, target);
        }
    }

    public boolean valid(int row, int col) {
        return row >= 0 && row < matrix.length
            && col >= 0 && col < matrix[row].length
            && enemy.equals(matrix[row][col]); // ✅ 使用 equals() 安全比较字符串
 

} public void printer(String[][] owo) { for (int i = 0; i < owo.length; i++) { for (int j = 0; j < owo[i].length; j++) { System.out.print(owo[i][j]); if (j < owo[i].length - 1) System.out.print(" "); } System.out.println(); } } }

⚠️ 注意事项与优化建议

  • 空指针防护:valid() 中应先检查 matrix != null 和 matrix[row] != null,避免运行时异常;
  • 递归深度风险:当前 recursive() 未标记已访问位置,可能导致无限递归或栈溢出——实际应引入 boolean[][] visited 或就地标记(如设为 null 或特殊占位符);
  • 输入解析健壮性:args[1] 解析使用 split(",") 比 substring() 更安全;矩阵字符串解析逻辑(如 co/3)需与真实输入格式对齐,建议补充单元测试验证;
  • 职责分离:可进一步将矩阵解析、填充逻辑、输出分别封装为独立类(如 MatrixParser、FloodFillEngine),提升可测试性。

重构后,MatrixRefill 成为一个真正可实例化、可复用、可单元测试的组件。例如,你可以在 JUnit 中轻松编写如下测试:

@Test
void testMultipleInstances() {
    MatrixRefill m1 = new MatrixRefill();
    m1.run(new String[]{"K,K,K-Y,Y,M-M,M,M", "1,1", "S"});

    MatrixRefill m2 = new MatrixRefill();
    m2.run(new String[]{"A,B-C,D", "0,0", "X"}); // 彼此状态完全隔离
}

这才是 Java 面向对象编程的正确实践起点。