Decoupling Classes with Interfaces in OOP
A practical guide to using interfaces for decoupling tightly bound classes, illustrated with an Android development example.
While building a Login module for an Android application, I encountered a common coupling problem. The Login class needed to call three methods on the calling Activity, which created a direct dependency between the two.
The Problem
The Login class was tightly coupled to a specific Activity. Reusing it from a different Activity would require modifying the Login class itself, violating the Open/Closed Principle.
The Solution: Define an Interface
By introducing an interface, we establish a contract that any caller must fulfill:
public interface LoginCallback {
void onLoginSuccess(User user);
void onLoginFailed(String error);
void onLoginProgress(int percent);
}
Now the Login class depends only on the interface, not on any concrete Activity:
public class LoginManager {
private LoginCallback callback;
public LoginManager(LoginCallback callback) {
this.callback = callback;
}
public void login(String username, String password) {
// perform login
callback.onLoginSuccess(user);
}
}
Any Activity that implements LoginCallback can use LoginManager without modification. The class is now reusable, testable, and decoupled from its consumers. This is a core principle of good object-oriented design.