重构目标:将系统的核心操作抽象为接口,从而解耦业务逻辑与具体实现。后续可以轻松替换存储方式(如从内存换成数据库)或增加新功能

 

1. 定义核心接口

 

```java

// 学生实体类

public class Student {

    private String id;

    private String name;

    private int age;

    // 构造方法、getter/setter 省略

}

 

// 学生管理接口 - 定义所有对外提供的操作

public interface StudentService {

    boolean addStudent(Student student);

    boolean deleteStudent(String id);

    boolean updateStudent(Student student);

    Student findStudentById(String id);

    List<Student> findAllStudents();

}

```

 

---

 

2. 基于内存的实现(原有系统可能长这样)

 

```java

// 原来的实现:直接使用 ArrayList,业务代码与具体存储耦合

public class MemoryStudentManager {

    private List<Student> students = new ArrayList<>();

 

    public boolean addStudent(Student s) { ... }

    public Student findStudentById(String id) { ... }

    // ...

}

```

 

---

 

3. 重构:让实现类实现接口

 

```java

// 重构后:实现 StudentService 接口

public class MemoryStudentService implements StudentService {

    private List<Student> students = new ArrayList<>();

 

    @Override

    public boolean addStudent(Student student) {

        if (findStudentById(student.getId()) != null) {

            return false; // 已存在

        }

        return students.add(student);

    }

 

    @Override

    public boolean deleteStudent(String id) {

        return students.removeIf(s -> s.getId().equals(id));

    }

 

    @Override

    public boolean updateStudent(Student student) {

        Student old = findStudentById(student.getId());

        if (old == null) return false;

        old.setName(student.getName());

        old.setAge(student.getAge());

        return true;

    }

 

    @Override

    public Student findStudentById(String id) {

        return students.stream()

                .filter(s -> s.getId().equals(id))

                .findFirst()

                .orElse(null);

    }

 

    @Override

    public List<Student> findAllStudents() {

        return new ArrayList<>(students);

    }

}

```

 

---

 

4. 使用接口编程(客户端代码)

 

```java

public class StudentManagementSystem {

    private StudentService studentService;

 

    // 通过构造方法注入具体的实现(依赖注入)

    public StudentManagementSystem(StudentService studentService) {

        this.studentService = studentService;

    }

 

    public void showAllStudents() {

        studentService.findAllStudents().forEach(System.out::println);

    }

 

    // 其他业务方法...

}

 

// 主程序

public class Main {

    public static void main(String[] args) {

        // 只需替换这一行,就可以切换存储方式

        StudentService service = new MemoryStudentService();

        // StudentService service = new DatabaseStudentService(); // 未来扩展

 

        StudentManagementSystem system = new StudentManagementSystem(service);

        system.addStudent(new Student("1", "张三", 20));

        system.showAllStudents();

    }

}

```

 

---

 

5. 重构带来的好处

 

方面 重构前(具体类) 重构后(接口)

扩展性 要换存储方式必须修改大量代码 新增 DatabaseStudentService 即可,符合开闭原则

测试性 单元测试必须依赖真实的列表 可以传入 Mock 实现,便于隔离测试

可维护性 业务逻辑与存储细节混杂 接口清晰定义了契约,实现者各司其职

多态性 不支持多种管理策略 可以用同一个 StudentManagementSystem 配合不同实现

 

---

 

6. 接口定义中的进阶设计(可选)

 

你还可以在接口中添加默认方法或静态方法,提供公共逻辑:

 

```java

public interface StudentService {

    // 核心抽象方法 ...

    

    // 默认方法:检查学生是否成年

    default boolean isAdult(Student student) {

        return student.getAge() >= 18;

    }

    

    // 静态方法:创建默认的内存实现

    static StudentService newMemoryInstance() {

        return new MemoryStudentService();

    }

}

```

 

使用时:StudentService service = StudentService.newMemoryInstance();

 

---

 

总结

 

通过接口的定义,将学生管理系统的操作契约与具体实现分离。这是面向对象设计中的面向接口编程原则,也是 Spring 等框架的核心思想。重构后的系统可以轻松应对需求变化(如从内存存储改为数据库存储),同时极大提升了代码的可测试性和可维护性。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐