What is callback ?
Callback is typically delegating part of its execution to more appropriate owner rather than doing on its own. Just like SoC (Separation of Concern).
It is also useful in notifying other when something happens.
In C++ callback can be easily achieved by function pointer but it Java as there is no function pointer we need to achieve it through interface.
It is like listener which when register will invoke a particular method.
Use Case:
We will take use case of Bank which is one of my favorite also.
Lets say Bank as an entity want to concentrate on the clearing part debit/credit and what to separate out the transaction logging (Separation of Concern) to some one else.
So here the transaction logging system will be notified when any debit or credit happens.
Lets start with BankAccount entity.
This is just a plain POJO to hold the bank account data.
package com.milind.callback.Bank;
/**
*
* @author milind
*/
public class BankAccount {
private int balance;
private int accountNumber;
public int getAccNumber() {
return accountNumber;
}
public BankAccount(int accountNumber, int balance) {
this.accountNumber = accountNumber;
this.balance = balance;
System.out.println("Initial Balance: " + balance);
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
}
Now lets defined the event which we need to capture.
package com.milind.callback.Bank;
/**
*
* @author milind
*/
public interface BankAccountEvent {
public void creditEvent(BankAccount acc, int amt);
public void debitEvent(BankAccount acc, int amt);
}
Now lets have the Bank entity which will also be EventNotifier.
When ever any deposit or withdrawal happens it will notify the BankTransactionLogging System.
package com.milind.callback.Bank;
/**
*
* @author milind
*/
public class Bank {
private BankAccountEvent events;
public Bank(BankAccountEvent events) {
this.events = events;
}
/**
* Depositing in any account
* @param acc
* @param amount
*/
public void deposit(BankAccount acc, int amount) {
System.out.println("Depositing : "+amount + " in account No: "+acc.getAccNumber());
acc.setBalance(acc.getBalance()+amount);
events.creditEvent(acc, amount);
}
/**
* Crediting in any account
* @param acc
* @param amount
*/
public void withdraw(BankAccount acc, int amount) {
System.out.println("Withdrawing : " + amount + " from account No: " + acc.getAccNumber());
acc.setBalance(acc.getBalance() - amount);
events.debitEvent(acc, amount);
}
}
Finally BankTransactionLogging which will act as CallMe.
package com.milind.callback.Bank;
/**
*
* @author milind
*/
public class BankTransactionLogging implements BankAccountEvent{
private Bank bank;
public BankTransactionLogging() {
this.bank = new Bank(this);
}
/**
* This will be callback when any credit happens in Bank
* @param acc
* @param amt
*/
public void creditEvent(BankAccount acc, int amt) {
System.out.println("Credit Logging for Bank Account No: "+acc.getAccNumber()+" amount: "+amt);
}
/**
* This will be callback when any debit happens in Bank
* @param acc
* @param amt
*/
public void debitEvent(BankAccount acc, int amt) {
System.out.println("Debit Logging for Bank Account No: "+acc.getAccNumber()+" amount: "+amt);
}
}
Testing:
package com.milind.callback.Bank;
/**
*
* @author milind
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// Creating the Bank Account
BankAccount account = new BankAccount(501, 10000);
// Creating the transaction logging object
BankTransactionLogging log = new BankTransactionLogging();
// Creating the Bank
Bank bank = new Bank(log);
// Depositing the amount 300
bank.deposit(account, 300);
// Withdrawing the amount 700
bank.withdraw(account,700);
// Doing for another account
BankAccount account2 = new BankAccount(999, 4000);
bank.deposit(account2, 100);
bank.withdraw(account2, 50);
//Final Balance
System.out.println("Final Balance in accout "+account.getAccNumber() +": "+account.getBalance());
System.out.println("Final Balance in accout "+account2.getAccNumber() +": "+account2.getBalance());
}
}
Out Come:
Initial Balance: 10000
Depositing : 300 in account No: 501
Credit Logging for Bank Account No: 501 amount: 300
Withdrawing : 700 from account No: 501
Debit Logging for Bank Account No: 501 amount: 700
Initial Balance: 4000
Depositing : 100 in account No: 999
Credit Logging for Bank Account No: 999 amount: 100
Withdrawing : 50 from account No: 999
Debit Logging for Bank Account No: 999 amount: 50
Final Balance in accout 501: 9600
Final Balance in accout 999: 4050
So you can see how the bank had delegate the transaction logging and how the Logging system is getting notified as and when an event occur.