Showing posts with label design pattern. Show all posts
Showing posts with label design pattern. Show all posts

Friday, February 4, 2011

Structural Design Pattern : Composite

Composite Design Pattern:
Word composite mean object contain another object.

Composite Pattern is Tree Structure of simple and composite objects to represent part-whole hierarchy.


Classic real time Example is the Family hierarchy. Lets try to put it into some design


( Click to enlarge)


Code:

Component:

package com.milind.gof.structural.composite;

/**
*
* @author milind
*/
public interface Family {

public void print();

}

Composite:

package com.milind.gof.structural.composite;

import java.util.ArrayList;

/**
*
* @author milind
*/
public class Parnet implements Family{


private String name;
private ArrayList arr;

public Parnet(String name) {
this.name = name;
this.arr = new ArrayList() ;
}

public void addChild(Family ch) {
this.arr.add(ch);
}

public void print() {
for(Family c : arr) {
System.out.println(c);
if(c instanceof Parnet) {
c.print();
}
}
}

@Override
public String toString() {
return "Parent: "+this.name;
}
}

Leaf:

package com.milind.gof.structural.composite;

/**
*
* @author milind
*/
public class Child implements Family{

private String name;

public Child(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {

return "Child: "+ this.name;
}

public void print() {
}
}

Client:

package com.milind.gof.structural.composite;

/**
*
* @author milind
*/
public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {

Parnet dhirubhai = new Parnet("Dhirubhai");
Parnet anil = new Parnet("Anil");
Parnet mukesh = new Parnet("Mukesh");

Child anil_1 = new Child("Anil_1");
Child anil_2 = new Child("Anil_2");

Child M1 = new Child("M1");
Child M2 = new Child("M2");

//Adding Anil children
anil.addChild(anil_1);
anil.addChild(anil_2);
//Adding Mukesh Children
mukesh.addChild(M1);
mukesh.addChild(M2);
//Adding anil and Mukesj to dhirubhai.
dhirubhai.addChild(anil);
dhirubhai.addChild(mukesh);
//printing dhirubhia's family.
dhirubhai.print();
}
}

Wednesday, February 2, 2011

Behavioral Design Pattern: State

State Design Pattern:

State pattern is to alter an object behavior when its state changes.

It is behavioral software design pattern.

Classic real time example of state pattern is ToggleButton which when press first becomes on and when press again becomes off.

So if you want to implement that toggle button you can use the state pattern so that its state change at runtime.

Following is the class diagram for the same.




(Click to Enlarge)

Code :
State

package com.milind.design.pattern.gof.behavioral;

/**
* This is the abstract state
* @author milind
*/
public interface ButtonState {

public void pressButton(ToggleButton btn);

}

Context

package com.milind.design.pattern.gof.behavioral;
/**
* This is the context which will be called by the client.
* @author milind
*
*/

public class ToggleButton {

private ButtonState state;

public ToggleButton() {
// Making the on state in begining
this.state = new OnState();
}

public ButtonState getState() {
return state;
}

public void setState(ButtonState state) {
this.state = state;
}

public void pressButton() {
this.state.pressButton(this);
}
}

Concrete On State:
package com.milind.design.pattern.gof.behavioral;

/**
* Concrete State
* @author milind
*/
public class OnState implements ButtonState{

public void pressButton(ToggleButton btn) {

System.out.println("Light Is Switched On ...");
btn.setState(new OffState());
}
}

Concrete Off State
package com.milind.design.pattern.gof.behavioral;

/**
* Concrete State
* @author milindaol
*/
public class OffState implements ButtonState{

public void pressButton(ToggleButton btn) {
System.out.println("Light Is Switched Off ...");
btn.setState(new OnState());
}

}

Client
package com.milind.design.pattern.gof.behavioral;
/**
*
* @author milindaol
*/
public class Client {

public static void main(String[] args) {

//Creating the Context
ToggleButton btn = new ToggleButton();
//Swithchin on the light.
btn.pressButton();
//Swithchin off the light.
btn.pressButton();
//Testing for three times
for(int i=0;i<3;>
btn.pressButton();
}
}
}





Monday, January 31, 2011

Callback in Java

Recently I was approached by my friend to explain him how callback can be achieved in Java. I told him to Google it and find out the stuff, but to my surprise there is no concrete use case available on net and this thought me of creating a blog on callback.


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.