Java > Object-Oriented Programming (OOP) > Abstraction > Abstract Classes
Abstract Class Example: Data Access Object (DAO)
This example demonstrates abstraction in the context of a Data Access Object (DAO) pattern. We define an abstract `AbstractDAO` class that provides a common interface for accessing data. Concrete DAO classes (e.g., `UserDAO`, `ProductDAO`) extend the abstract class and provide implementations for specific data entities. This simplifies data access logic and promotes code maintainability.
Code Snippet: Abstract DAO and Concrete Implementations
The `AbstractDAO` class is declared as `abstract` and uses generics (`
// Abstract DAO class
abstract class AbstractDAO<T> {
// Abstract method to get an entity by ID
public abstract T getById(int id);
// Abstract method to save an entity
public abstract void save(T entity);
// Abstract method to delete an entity
public abstract void delete(T entity);
// Concrete method for common operations (e.g., logging)
protected void logAction(String action) {
System.out.println("DAO Action: " + action);
}
}
// User class (example data entity)
class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
// UserDAO class extending AbstractDAO
class UserDAO extends AbstractDAO<User> {
@Override
public User getById(int id) {
// Simulate fetching user from a database
logAction("Fetching user with ID: " + id);
return new User(id, "User " + id);
}
@Override
public void save(User user) {
// Simulate saving user to a database
logAction("Saving user: " + user.getName());
System.out.println("User saved: " + user.getName());
}
@Override
public void delete(User user) {
// Simulate deleting user from a database
logAction("Deleting user: " + user.getName());
System.out.println("User deleted: " + user.getName());
}
}
// Example usage
public class Main {
public static void main(String[] args) {
UserDAO userDao = new UserDAO();
User user = userDao.getById(123);
System.out.println("User ID: " + user.getId() + ", Name: " + user.getName());
userDao.save(user);
userDao.delete(user);
}
}
Concepts Behind the Snippet
Real-Life Use Case
In a web application that interacts with a database, you would have different DAOs for different entities like users, products, orders, etc. An abstract DAO class could define common methods like `getConnection()`, `closeConnection()`, and error handling logic. Each concrete DAO would then implement methods like `getUserById()`, `saveProduct()`, etc., using the shared connection and error handling logic.
Best Practices
Interview Tip
Understand the benefits of using the DAO pattern, such as separation of concerns, improved testability, and reduced code duplication. Be able to explain how abstract classes can be used to implement the DAO pattern.
When to Use Them
Use abstract DAOs when you have multiple data entities that require similar data access operations. This promotes code reuse and simplifies data access logic. They are most useful in applications where you interact with databases or other data sources.
Memory Footprint
Similar to the previous example, the abstract DAO class itself has minimal memory footprint. The concrete implementations (e.g. `UserDAO`) will have memory footprint related to the state they manage, any cached data, or database connection objects. Optimizing database connections will generally have the largest effect on reducing memory usage.
Alternatives
Pros
Cons
FAQ
-
What is the purpose of using generics in the AbstractDAO class?
Generics allow the `AbstractDAO` to work with different types of data entities without needing to be rewritten for each type. This promotes code reuse and type safety. -
Can I have multiple concrete DAO classes extending the same AbstractDAO?
Yes, you can have multiple concrete DAO classes extending the same `AbstractDAO`. Each concrete DAO would handle a different data entity (e.g., `UserDAO`, `ProductDAO`, `OrderDAO`). -
Is it necessary to have an abstract method in an abstract class?
No, it's not strictly necessary. An abstract class can exist without having any abstract methods. However, the main purpose of using an abstract class is often to define a common interface with some abstract methods that subclasses must implement.