De-Coupling Classes Using Interface


De-Coupling Classes Using Interface. Few days back we came up with a problem where we have implemented a Login Class in an Android Application. I specifically mentioned “Android Application” as the scenario i am about to mention is not a Perfect MVC as in mobile application we need to call view direct from controller classes rather than from framework for many reasons that i am not going to explore here.

Scenario:

The Login class required to call 3 methods of caller class.

  1. Update Progress Bar.
  2. Login Success.
  3. Login Failure.

for the purpose we just passed caller class’s reference in constructor.

public class MainScreen {

	public void doLogin(){
		String user = "";//get from view
		String pass = "";//get from view

		Login login = new Login(this);
		login.performLogin(user, pass);
	}

	public void updateProgressBar(int processPercentage){
		//update progress bar
	}

	public void onSuccess(String message){
		//goto home page
	}

	public void onFailure(String message){
		//show error
	}
}

public class Login {

	private int loginStatus = 0;
	private MainScreen mainScreen = null;

	public Login(MainScreen mScreen) {
		mainScreen = mScreen;
	}

	public void performLogin(String user, String pass){
		//process login and set loginStatus to 1 if successful
		mainScreen.updateProgressBar(50);

		if(loginStatus==1){
			mainScreen.onSuccess("Success!.");
		}

		mainScreen.onFailure("Login Failed!");
	}

}

Problem:

Later we required same Login class at another place but we were unable to use it as it was coupled with caller class (with 3 methods to be very specific).

Solution:

We introduced 2 interfaces. One Having ProgressBar method prototype and other having onSuccess and onFailure method prototypes.
Implement caller class of Login with these two Interfaces.
Finally Passed 2 interface references instead of one caller class reference in Login class constructor.
In this way any class now can be caller class if it implements these two interfaces.

public interface InterfaceProgressBar{
	public void updateProgressBar(int processPercentage);
}

public interface InterfaceResponseManager{
	public void onSuccess(String message);
	public void onFailure(String message);
}

public class MainScreen implements InterfaceProgressBar, InterfaceResponseManager {

	public void doLogin(){
		String user = "";//get from view
		String pass = "";//get from view

		Login login = new Login(this, this);
		login.performLogin(user, pass);
	}

	public void updateProgressBar(int processPercentage){
		//update progress bar
	}

	public void onSuccess(String message){
		//goto home page
	}

	public void onFailure(String message){
		//show error
	}
}

public class Login {

	private int loginStatus = 0;
	private InterfaceProgressBar progressBar = null;
	private InterfaceResponseManager responseManager = null;

	public Login(InterfaceProgressBar pBar, InterfaceResponseManager rManager) {
		progressBar = pBar;
		responseManager = rManager;
	}

	public void performLogin(String user, String pass){
		//process login and set loginStatus to 1 if successful
		progressBar.updateProgressBar(50);

		if(loginStatus==1){
			responseManager.onSuccess("Success!.");
		}

		responseManager.onFailure("Login Failed!");
	}

}

Of The Top of Programmer’s Head:

If you handle null reference pointers for Both interfaces in Login class and pass ‘null’ in login class constructor then any class even not implementing interfaces can same use login class.

public class AnotherClass {

	public void doLogin(){
		String user = "";//get from view
		String pass = "";//get from view

		Login login = new Login(null, null);
		login.performLogin(user, pass);
	}
}

class Login {

	private int loginStatus = 0;
	private InterfaceProgressBar progressBar = null;
	private InterfaceResponseManager responseManager = null;

	public Login(InterfaceProgressBar pBar, InterfaceResponseManager rManager) {
		progressBar = pBar;
		responseManager = rManager;
	}

	public void performLogin(String user, String pass){
		//process login and set loginStatus to 1 if successful
		if(progressBar!=null){
			progressBar.updateProgressBar(50);
		}

		if(loginStatus==1){
			if(responseManager!=null){
				responseManager.onSuccess("Success!.");
			}
		}

		if(responseManager!=null){
			responseManager.onFailure("Login Failed!");
		}
	}

}