模式介绍

数据访问对象模式(Data Access Object Pattern)或 DAO 模式用于把低级的数据访问 API 或操作从高级的业务服务中分离出来。该模式用于以下场景:

  • 需要将数据访问逻辑与业务逻辑分离
  • 需要支持多种数据源
  • 需要统一数据访问接口

使用场景

  • 需要访问数据库的应用程序
  • 需要支持多种数据源的系统
  • 需要统一数据访问接口的项目
  • 需要实现数据访问层缓存的应用

代码示例

// 实体类
public class Student {
    private int id;
    private String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    // getter和setter方法
}

// 数据访问对象接口
public interface StudentDao {
    List getAllStudents();
    Student getStudent(int id);
    void updateStudent(Student student);
    void deleteStudent(Student student);
}

// 数据访问对象实现
public class StudentDaoImpl implements StudentDao {
    private List students;

    public StudentDaoImpl() {
        students = new ArrayList<>();
        students.add(new Student(1, "张三"));
        students.add(new Student(2, "李四"));
    }

    @Override
    public List getAllStudents() {
        return students;
    }

    @Override
    public Student getStudent(int id) {
        return students.stream()
            .filter(student -> student.getId() == id)
            .findFirst()
            .orElse(null);
    }

    @Override
    public void updateStudent(Student student) {
        students.set(student.getId() - 1, student);
    }

    @Override
    public void deleteStudent(Student student) {
        students.remove(student.getId() - 1);
    }
}

// 使用示例
public class DaoPatternDemo {
    public static void main(String[] args) {
        StudentDao studentDao = new StudentDaoImpl();

        // 输出所有学生
        for(Student student : studentDao.getAllStudents()) {
            System.out.println("Student: [ID : " + student.getId() + ", Name : " + student.getName() + "]");
        }

        // 更新学生
        Student student = studentDao.getStudent(1);
        student.setName("王五");
        studentDao.updateStudent(student);

        // 获取更新后的学生
        student = studentDao.getStudent(1);
        System.out.println("Student: [ID : " + student.getId() + ", Name : " + student.getName() + "]");
    }
}

优缺点

优点

  • 分离数据访问逻辑和业务逻辑
  • 支持多种数据源
  • 便于维护和扩展
  • 提高代码复用性

缺点

  • 增加了代码复杂度
  • 需要编写更多的代码
  • 可能影响系统性能

注意事项

  • 合理设计数据访问接口
  • 注意数据访问的性能优化
  • 考虑事务管理
  • 合理使用连接池