Showing posts with label Behavioral Design Pattern. Show all posts
Showing posts with label Behavioral Design Pattern. Show all posts

Wednesday, February 11, 2015

Visitor Design Pattern

Design Pattern > Behavioral Design Pattern > Visitor Design Pattern

As per GOF the intention of visitor pattern is to "Represents an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates"


Let's understand it with an example. Suppose, you have created a basic banking application and your account structure is following :

Interface Account {

    int withdraw(int amount);
    int deposit(int amount);
}

class CheckingAccount Implements Account {
    String AccountType;
    int AccountBalance;

// getter setter

int withdraw(int amount){
// business logic
}

int deposit(int amount){
// business logic
}
}

class SavingsAccount Implements Account {
    String AccountType;
    int AccountBalance;

// getter setter

int withdraw(int amount){
// business logic
}

int deposit(int amount){
// business logic
}
}

So, client can perform deposit and withdrawal to their account, assume a new requirement arrive from the bank that offers all account holders to invest their say 10 percent money from savings account in a new Investment Account and bank needs to calculate total invested amount from across all the account.
One way you can modify the Account interface with doInvest operation and change all it's type classes structure. like below :

Interface Account {

    int withdraw(int amount);
    int deposite(int amount);

    int doInvest(int amount);
}

class CheckingAccount Implements Account {

// existing code

int doInvest(int amount){

// business logic
}

}

class SavingsAccount Implements Account {

// existing code

int doInvest(int amount){

// business logic
}

}

The problem in this approach is that in the feauture if new requirement come then you have to again change all the class structure.
Visitor pattern helps in these kind of situation.

Solution :
In visitor Pattern we design Element Interface( in our example Account interface) in suach a way so that it shouold not be changed with new requirements.Then the main interface Visitor whose objective is to perform action on Element classes.Visitor is desigend as per new requirement.

the key terms in this pattern are -
Element -

  • An Interface ( Account) with accept method whose parameter is a Visitor 

Concrete Element -

  • Implements Element interface
  • Calls visit method of Visitor object

Visitor -

  • An interface with visit method whose patameter is an Element

Concrete Visitor -

  • Implements Visitor interface
  • Actual operation (doInvest ) happens in visit method

ClientClass -

  • Create Element objects
  • Create Visitor object
  •        call accept method of elements as per requirement



Java Implementation :

/**
 *  Element interface
 */
package com.kmingle.visitor;

public interface Account {

double accept(AccountVisitor visitor);
}


/**
 * Concrete Element class
 */
package com.kmingle.visitor;

public class CheckingAccount implements Account {

private String accountType;
private int AccountBalance;

public CheckingAccount(String acType, int acBal){
this.accountType = acType;
this.AccountBalance = acBal;
}

public String getAccountType() {
return accountType;
}


public void setAccountType(String accountType) {
this.accountType = accountType;
}


public int getAccountBalance() {
return AccountBalance;
}


public void setAccountBalance(int accountBalance) {
AccountBalance = accountBalance;
}


/* (non-Javadoc)
* @see com.kmingle.visitor.Account#accept(com.kmingle.visitor.AccountVisitor)
*/
@Override
public double accept(AccountVisitor visitor) {

return visitor.visit(this);
}

}


/**
 * Concrete Element class
 */
package com.kmingle.visitor;

public class SavingsAccount implements Account {

private String accountType;
private int AccountBalance;

public SavingsAccount(String acType, int acBal){
this.accountType = acType;
this.AccountBalance = acBal;
}

public String getAccountType() {
return accountType;
}


public void setAccountType(String accountType) {
this.accountType = accountType;
}


public int getAccountBalance() {
return AccountBalance;
}


public void setAccountBalance(int accountBalance) {
AccountBalance = accountBalance;
}


/* (non-Javadoc)
* @see com.kmingle.visitor.Account#accept(com.kmingle.visitor.AccountVisitor)
*/
@Override
public double accept(AccountVisitor visitor) {

return visitor.visit(this);
}

}


/**
 *  Visitor interface
 */
package com.kmingle.visitor;

public interface AccountVisitor {

double visit(Account acount);

}


/**
 * Concrete Visitor Class
 */
package com.kmingle.visitor;

public class InvestmentAccountVisitor implements AccountVisitor {

/* (non-Javadoc)
* @see com.kmingle.visitor.AccountVisitor#visit(com.kmingle.visitor.Account)
*/
@Override
public double visit(Account account) {

double investedAmount = 0;

String className = account.getClass().getSimpleName();

if(className.equals("SavingsAccount")){
System.out.println("Account Type is SavingsAccount");
investedAmount = ((SavingsAccount)account).getAccountBalance()*0.1;
System.out.println("savings account balance = "+ ((SavingsAccount)account).getAccountBalance());
System.out.println("invested amount = "+ investedAmount);
return investedAmount;
}
else if(className.equals("CheckingAccount")){
System.out.println("Account Type is CheckingAccount");
System.out.println("can't invest from checking account");
}
else{
System.out.println("invalid account");
}
return 0;

}

}


/**
 * Visitor Client
 */
package com.kmingle.visitor;

import java.beans.Visibility;
import java.util.ArrayList;

public class InvestmentVisitorClient {

public static void main(String[] args) {

ArrayList accountList = new ArrayList();

accountList.add(new CheckingAccount("checking", 100));

accountList.add(new SavingsAccount("savings", 200));

accountList.add(new SavingsAccount("savings", 500));

double totalInvesteAmount = calculateInvestedAmount(accountList);

System.out.println("Total Invested Amount = "+ totalInvesteAmount);
}

private static double calculateInvestedAmount(ArrayList accountList) {

AccountVisitor visitor = new InvestmentAccountVisitor();

double investedAmount = 0;

for(Account account : accountList){

investedAmount = investedAmount + account.accept(visitor);
}

return investedAmount;
}

}


Output :

Account Type is CheckingAccount
can't invest from checking account
Account Type is SavingsAccount
savings account balance = 200
invested amount = 20.0
Account Type is SavingsAccount
savings account balance = 500
invested amount = 50.0
Total Invested Amount = 70.0


Further, you can create as many visitors as per your requirement without changing the structure of Element interface/classes.

Tuesday, February 3, 2015

Template Method Design Pattern

Design Pattern > Behavioral Design Pattern > Template Method Design Pattern

In some scenarios we want to write classes that follow certain algorithm structure but at the same allow different classes to define their own implementation of steps of algorithm. Template method pattern is helpful in these scenarios.

As per GOF the intent of template method pattern is to "Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure."

It's not necessory to define all the steps of an algorithm. it depends of your requirements whether you wnat to use default step/operation of given algorithm from super class or want to define some or all operations/steps in your sub class.

There is a template method in super class which declare the order of algorithm operations/steps and sub classes need to define/override these operations( either some or all).At runtime template method calls the sub class operations in an order.

Key Terms :
Abstract Class - 

  • Class with template method
  • Subclasses can not override it's template method
  • Subclasses need to override it's operations declared in template method


Note - Super class need not to be abstract. in that case we need to call a hooks.The hooks are generally empty methods that are called in superclass (and does nothing because are empty), but can be implemented in subclasses.

Concrete Class - 

  •        Sub class that override operations declared in template method

Client Class - 

  • Create subclass instance that refers to superclass
  • calls template method of superclass to execute the algorithm


Java Implementation :

In this example an algorithm is defined to book a ticket in super class BookTicket and there are two subclasse BookTicketOnline and BookTicketIvr ( on phone call )


/**
 * An abstract class with template method
 */
package com.kmingle.template;

public abstract class BookMovieTicket {

public abstract void login();

public abstract void selectSource();

public abstract void selectDestination();

public void enterDetails(){
System.out.println("personal details entered from system");
}

public abstract void makePayment();

public final void bookTicket(){
login();
selectSource();
selectDestination();
enterDetails();
makePayment();
}
}


/**
 * Concrete Class
 */
package com.kmingle.template;

public class BookTicketOnline extends BookMovieTicket {

/* (non-Javadoc)
* @see com.kmingle.template.BookMovieTicket#login()
*/
@Override
public void login() {

System.out.println("online logged in");

}

/* (non-Javadoc)
* @see com.kmingle.template.BookMovieTicket#selectSource()
*/
@Override
public void selectSource() {

System.out.println("online Source selected");

}

/* (non-Javadoc)
* @see com.kmingle.template.BookMovieTicket#selectDestination()
*/
@Override
public void selectDestination() {

System.out.println("online Destination selected");

}

/* (non-Javadoc)
* @see com.kmingle.template.BookMovieTicket#makePayment()
*/
@Override
public void makePayment() {

System.out.println("online payment done");

}

}


/**
 * Concrete Class
 */
package com.kmingle.template;

public class BookTicketIvr extends BookMovieTicket {

/* (non-Javadoc)
* @see com.kmingle.template.BookMovieTicket#login()
*/
@Override
public void login() {

System.out.println("Ivr logged in");
}

/* (non-Javadoc)
* @see com.kmingle.template.BookMovieTicket#selectSource()
*/
@Override
public void selectSource() {

System.out.println("Ivr source selected");

}

/* (non-Javadoc)
* @see com.kmingle.template.BookMovieTicket#selectDestination()
*/
@Override
public void selectDestination() {

System.out.println("Ivr destination selected");

}

/* (non-Javadoc)
* @see com.kmingle.template.BookMovieTicket#makePayment()
*/
@Override
public void makePayment() {

System.out.println("Ivr payment done");

}

}

/**
 * Client Class
 */
package com.kmingle.template;

public class TemplateMethodDemo {

public static void main(String[] args) {

System.out.println("Book ticket online");
BookMovieTicket book_ticket_online = new BookTicketOnline();
book_ticket_online.bookTicket();

System.out.println("\nBook ticket through Phone(Ivr)");
BookMovieTicket book_ticket_ivr = new BookTicketIvr();
book_ticket_ivr.bookTicket();

}

}


OutPut :

Book ticket online
online logged in
online Source selected
online Destination selected
personal details entered from system
online payment done

Book ticket through Phone(Ivr)
Ivr logged in
Ivr source selected
Ivr destination selected
personal details entered from system
Ivr payment done

Saturday, January 31, 2015

Strategy Design Pattern

Design Pattern > Behavioral Design Pattern > Strategy Design Pattern

As per GOF the intent of Strategy Design Pattern is to "Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it."

In Strategy Design Pattern we create number of different classes whose structures are same but differ in behaviour( i.e. same method name with different implementation) and appropriate object is decided at run time.

let's see with an example the benefit of strategy pattern.

Problem :
         Suppose you are working on a requirement to filter out the digits/numbers from a given string.Client class would be similer to following
   
     public String filterNumbers(String input) {

     // add logic to filter numbers from string

     return filteredString;
     }

Now, a new requirement come up to filter out the special characters, now client class need to be changed,

     public String filterNumbers(String input,String filterType ) {
if(filterType.equals("number"){
// add logic to filter numbers from input string
}
else if(filterType.equals("specialChar"){
// add logic to filter special characters from input string
}
     return filteredString;
     }

further if more requirements come then you have to change the client code again and again and that's not a good design.

Solution :
 Strategy Design Pattern helps in this situation, here we seperate client class with filterlogic.
 Key terms in this pattern are :
 1. Strategy :

  •                 An interface with doFilter method declaraction


 2. Concrete Strategy Class :

  • Implements Strategy interface with business logic to dofilter


 3. Context : 

  • Class with reference to Strategy interface 
  • Client code has access to this class methods
  • executs business login of Strategy object at runtime


 4. Client :

  • Create context objects and call dofilter method


Benefit here we got is that we can create different filter strategy and use them in client class without changing the existing design.

Java Implementation :


/**
 * Strategy interface
 */
package com.kmingle.strategy;

public interface Strategy {

void doFilter(String input);
}


/**
 * Concrete Strategy Class to filter out numbers from input
 */
package com.kmingle.strategy;

public class NumberStrategy implements Strategy {

/* (non-Javadoc)
* @see com.kmingle.strategy.Strategy#doFilter(java.lang.String)
*/
@Override
public void doFilter(String input) {

System.out.println("numbers filtered out from input string");

}

}


/**
 * Concrete Strategy Class to filter out special characters from input
 */
package com.kmingle.strategy;

public class SpecialCharStrategy implements Strategy {

/* (non-Javadoc)
* @see com.kmingle.strategy.Strategy#doFilter(java.lang.String)
*/
@Override
public void doFilter(String input) {

System.out.println("special characters filtered out from input string");

}

}


/** 
 * Context class
 */
package com.kmingle.strategy;


public class Context {

Strategy filterStrategy;

public Context(Strategy strategy){
filterStrategy = strategy;
}

public void doFilter(String input){
filterStrategy.doFilter(input);
}
}


/**
 * Client Class
 */
package com.kmingle.strategy;

public class StrategyDemo {

public static void main(String[] args) {

// create context with number filter strategy
Context context = new Context(new NumberStrategy());

// filter out number from input string
context.doFilter("input string 1234 @#$&");

// change same context to refer specialchar filter strategy
context = new Context(new SpecialCharStrategy());

// filter out special characters from input string
context.doFilter("input string 1234 @#$&");
}

}


Output :

numbers filtered out from input string
special characters filtered out from input string

Tuesday, January 27, 2015

State Design Pattern

Design Pattern > Behavioral Design Pattern > State Design Pattern

The intent of state design pattern is to allow the object to change it's behaviour when there is change in the state of object.

Key Terms :
State Interface - represents the different states involved


  • Declares method to perform action


Concrete State Class -


  • Has method to perform action


Context - This class maintains the current state and is the core of the state design pattern


  • Client has direct access to this class
  • Create and Maintain the current state
  • Provide interface to perform action through state class


Client -

  • Creates Context class instance
  • Creates State objects
  • Changes state of context


Benefits of State Design Pattern :


  • Puts all behavior associated with a state into one object
  • Allows state transition logic to be be incorporated into a state object rather than in a monolithic if or switch statement
  • Allows multiple states to be added to the object whithout changing the context class.


Java Implementation :

In this example Robot is a context whose states are walk and stop. RobotState is an State interface and there are two concreate State classes that implement State interface. Default state of Robot is StopState.
Clinet class is remote which can change the state of context ( Robot )

/**
 *  Context Class
 */
package com.kmingle.state;

public class Robot {

private RobotState roboState;

public Robot(){
roboState = new StopState();
}

public RobotState getRoboState() {
return roboState;
}

public void changeRobotState(RobotState roboState) {
this.roboState = roboState;
}

public void doAction(){
roboState.doAction(this);
}
}


/**
 *  State Interface
 */
package com.kmingle.state;

public interface RobotState {

public void doAction(Robot context);
}


/**
 * Concreate State Class
 */
package com.kmingle.state;

public class StopState implements RobotState {

/* (non-Javadoc)
* @see com.kmingle.state.RobotState#doAction(com.kmingle.state.Robot)
*/
@Override
public void doAction(Robot context) {
System.out.println(context.getRoboState().getClass().getSimpleName());
}

}


/**
 * Concreate State Class
 */
package com.kmingle.state;

public class WalkState implements RobotState {

/* (non-Javadoc)
* @see com.kmingle.state.RobotState#doAction(com.kmingle.state.Robot)
*/
@Override
public void doAction(Robot context) {
System.out.println(context.getRoboState().getClass().getSimpleName());
}

}


/**
 * Client Class
 */
package com.kmingle.state;

public class Remote {

public static void main(String[] args) {

Robot robo = new Robot();

robo.doAction();

robo.changeRobotState(new WalkState());

robo.doAction();

}

}

Friday, January 23, 2015

Observer Design Pattern

Design Pattern > Behavioral Design Pattern > Observer Design Pattern

In some scenarios you can see one to many relation between objects i.e. if there is change in state of parent object all child objects should get updated/notified.

Here, dependent objects can directly access the state of parent/observable object if we make state public to observers but it would fail the encpsulation principle and objects would be tightly coupled in this case.
Observer design pattern helps in this scenario.

In observer design pattern there are 3 clasess. Subject - whose change state is observed, Observer - observe subject for state change, Client - class which create instances of subject and observers, change state of subject.

Observer pattern is also know as publish-subscribe pattern.

Key Terms :

Subject -

  • An interface or abstract class
  • Contains a list of observers
  • provide interfaces to subscribe or unsubscribe observers objects


ConcreteSubject -

  • Implements/extends Subject
  • Stores its state information
  • notifies it's observers when state changes


Observer -

  • An interface or abstract class 
  • Has reference to subjet
  • Define a update state method for observers to make them in consistent with subject


ConcreateObserver -

  • Implements/extends Observer
  • Subscribe itself for subject state change while initializing
  • Implement a update state method for observers to make them in consistent with subject


Client -

  • Instantiate Subject
  • Instantiate Observers
  • Changes state of subject


Benefits of Using Observer Pattern :

Minimal coupling between the Subject and the Observer

  • Can reuse subjects without reusing their observers and vice versa
  • Observers can be added without modifying the subject
  • All subject knows is its list of observers
  • Subject does not need to know the concrete class of an observer, just that each observer implements the update interface
  • Subject and observer can belong to different abstraction layers

Support for event broadcasting

  • Subject sends notification to all subscribed observers
  • Observers can be added/removed at any time


Java Inplementation:
In key terms section we have seen the pseudo code, now let's see actual java implementation


/**
 * Subject abstract class
 */
package com.kmingle.observer;

import java.util.ArrayList;
import java.util.List;

public abstract class Publisher {

protected List observerList = new ArrayList();

public abstract void SubscribeMe(Observer observer);

public abstract void UnSubscribeMe(Observer observer);

}


/**
 *  Concrete Subject 
 */
package com.kmingle.observer;


public class EnglishPublisher extends Publisher {

private String state;

public String getState() {
return state;
}

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

/* (non-Javadoc)
* @see com.kmingle.observer.Publisher#SubscribeMe()
*/
@Override
public void SubscribeMe(Observer observer) {

observerList.add(observer);
System.out.println(observer.observerName+" subscribed");
}

/* (non-Javadoc)
* @see com.kmingle.observer.Publisher#UnSubscribeMe()
*/
@Override
public void UnSubscribeMe(Observer observer) {

observerList.remove(observer);
System.out.println(observer.observerName+" unsubscribed");

}

public void notifyObservers(){

for(Observer o : observerList){
o.update();
}
}

}


/**
 * Observer Interface
 */
package com.kmingle.observer;


public abstract class Observer {

String observerName;
protected Publisher publisher;
abstract void update();
}


/**
 * Concerete Observer
 */
package com.kmingle.observer;


public class EnglishSubsriber extends Observer {


public EnglishSubsriber(Publisher pub, String name){
this.observerName = name;
this.publisher = pub;
this.publisher.SubscribeMe(this);
}

/* (non-Javadoc)
* @see com.kmingle.observer.Observer#update()
*/
@Override
public void update() {

System.out.println("updated state in "+this.observerName +" is " +((EnglishPublisher) publisher).getState());
}

}


/**
 * Client Class
 */
package com.kmingle.observer;


public class ObserverDemo {


public static void main(String[] args) {

EnglishPublisher engPublisher = new EnglishPublisher();

new EnglishSubsriber(engPublisher, "Observer1");

new EnglishSubsriber(engPublisher, "Observer2");

System.out.println("changing state of subject");

engPublisher.setState("statechanged");

System.out.println("rechanging state of subject");

engPublisher.setState("REstatechanged");
}

}

OutPut :

Observer1 subscribed
Observer2 subscribed
changing state of subject
updated state in Observer1 is statechanged
updated state in Observer2 is statechanged
rechanging state of subject
updated state in Observer1 is REstatechanged
updated state in Observer2 is REstatechanged



Further, You can create more than one Publisher classes i.e. Subjects

Monday, January 19, 2015

Memento Design Pattern

Design Pattern > Behavioral Design Pattern > Memento Design Pattern

Sometimes it require to store the state of an object at somepoint and restore this state later.Memento pattern help in this case.
The intent of Memento design pattern is to store an object's internal state(outisde of this object) and restores it at later stage without violating the encaptulation principle.

Key Terms :
Originator -

  • The object whose state need to be saved
  • Has getter and setter for it's own state
  • Create and return memento object in method createMemento
  • get previous state from memento in method setMemento()

CareTaker -


  • Keeps list of mementos
  • Has addMemento method to add new memento to the list
  • return specific memento in getMemento method


Memento -


  • Is a POJO class
  • Set State of Originator
  • retuirn state of Originator in getState methd
  • Only Originator should assign and retrive its state


Client -

1. Create Originator, Caretaker objects
2. set State of Originator object
3. when state of originator needs to be saved then create Memento object by calling originator's createMemento method
4. Add memento to caretaker
repeat steps 2 to 4 as per your requirement to set states of Originator object
When need to restore originator state to previous state then
1. get memento object by calling getMemento on caretaker object
2. Set originator's state from the returned memento object in step 1 by calling originator's setMemento method
3. get restored state of Originator by callling it's getState method


Benefits of Using Memento Pattern :

Since object oriented programming dictates that objects should encapsulate their state it would violate this law if objects’ internal variables were accessible to external objects. The memento pattern provides a way of recording the internal state of an object in a separate object without violating this law

The memento eliminates the need for multiple creation of the same object for the sole purpose of saving its state.

The memento simplifies the Originator since the responsibility of managing Memento storage is no longer centralized at the Originator but rather distributed among the Caretakers

Java Implementation :
                In key terms section we have seen the pseudo code, now let's see actual java implementation


/**
 * Memento Class
 */
package com.kmingle.memento;

public class Memento {

String state;

public Memento(String _state){
state = _state;
}

public String getState(){
return state;
}
}

/**
 *  Originator class whose state needs to be stored/restored
 */
package com.kmingle.memento;


public class Originator {

private String state;

public String getState() {
return state;
}

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

public Memento createMemento(){
return new Memento(state);
}

public void setMemento(Memento memento){
state = memento.getState();
}
}

/**
 *  CareTaker Class
 */
package com.kmingle.memento;

import java.util.ArrayList;
import java.util.List;

public class CareTaker {

List mementoList = new ArrayList();

public void addMemento(Memento _memento){
mementoList.add(_memento);
}

public Memento getMemento(int i){
return mementoList.get(i);

}
}

/**
 * the demo class
 */
package com.kmingle.memento;

public class Client {

public static void main(String[] args) {

Originator org = new Originator();
CareTaker caretaker = new CareTaker();

org.setState("State1");
org.setState("state2"); // only store the state from here

Memento _memento = org.createMemento();
caretaker.addMemento(_memento);

org.setState("state3");

_memento = org.createMemento();
caretaker.addMemento(_memento);

org.setState("state4");
org.setState("state5");
// originator's current state
System.out.println("originator's current state : "+ org.getState());

// restore originator to previous state
_memento = caretaker.getMemento(1);
org.setMemento(_memento);
System.out.println("originator's restored state : "+ org.getState());

}

}

Wednesday, January 14, 2015

Mediator Design Pattern

Design Pattern > Behavioral Design Pattern > Mediator Design Pattern

There are scenarios when we create lots of classes which interact or communicate among each other and going forward most of the classes have many to many relation.
Here the problem is that now application become difficult to maintaine, beacause change in once class may require change in several other classes too and this violates the principle of high cohesion and loose coupling.
To resolve this problem we can use mediator design pattern where a mediator class work as a central hub for communicating classes and defince a set of rules for them to communicate. By this mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

Benefits of Using Mediator Pattern :

  • The mediator encapsulate the logic of mediation between the colleagues. so its easy to maintain, understand and change the communication logic.
  • The colleague classes(classes in communication) are totally decoupled. Adding a new colleague class is very easy due to this decoupling level.
  • The colleague objects need to communicate only with the mediator objects. Practically the mediator pattern reduce the required communication channels(protocols) from many to many to one to many and many to one.


Key Terms :
Mediator - defines an interface for communicating with Colleague objects.
ConcreteMediator - knows the colleague classes and keep a reference to the colleague objects.
- implements the communication and transfer the messages between the colleague classes
Colleague classes - keep a reference to its Mediator object
 - communicates with the Mediator whenever it would have otherwise communicated with another Colleague.


Java Implementation :

/**
 * Mediator Interface
 */
package com.jaistutorial.mediator;

import java.util.List;


public interface ChatRoom {

void registerUser(User collegue);
void BroadcastMessage(User collegue,String message);
}


/**
 * Mediator Class
 */
package com.jaistutorial.mediator;

import java.util.ArrayList;
import java.util.List;


public class ChatRoomeImpl implements ChatRoom {

List colleagueList = new ArrayList();
/* (non-Javadoc)
* @see com.jaistutorial.mediator.ChatRoom#registerUser(com.jaistutorial.mediator.User)
*/

public ChatRoomeImpl(String chatRoomName){
System.out.println(chatRoomName + " initialized");
}
@Override
public void registerUser(User collegue) {

System.out.println("regestering new collegue "+ collegue.getname());
colleagueList.add(collegue);

}

/* (non-Javadoc)
* @see com.jaistutorial.mediator.ChatRoom#BroadcastMessage(com.jaistutorial.mediator.User, java.lang.String)
*/
@Override
public void BroadcastMessage(User senderCollegue, String message) {

for(User user : colleagueList){
if(user!=senderCollegue){ // sender should not receive his own message
user.receiveMessage(message);
}
}

}

}


/**
 * Colleague Interface
 */
package com.jaistutorial.mediator;


public interface User {

void setname(String name);
String getname();
void sendMessage(ChatRoom mediator,String message);
void receiveMessage(String message);
}


/**
 * Colleague Class
 */
package com.jaistutorial.mediator;


public class UserImpl implements User {

private String userName;

/* (non-Javadoc)
* @see com.jaistutorial.mediator.User#sendMessage(com.jaistutorial.mediator.ChatRoom, java.lang.String)
*/
@Override
public void sendMessage(ChatRoom mediator, String message) {

mediator.BroadcastMessage(this, message);
}

/* (non-Javadoc)
* @see com.jaistutorial.mediator.User#receiveMessage(java.lang.String)
*/
@Override
public void receiveMessage(String message) {

System.out.println(this.getname() + " received message : " + message);
}
@Override
public void setname(String name) {
this.userName  = name;

}
@Override
public String getname() {
return userName;
}

}


/**
 * Client Class
 */
package com.jaistutorial.mediator;


public class MediatorDemo {

public static void main(String[] args) {

// create a mediator - chatroom1
ChatRoomeImpl chatroom1 = new ChatRoomeImpl("chatroom1");
// create colleagues
UserImpl user1 = new UserImpl();
user1.setname("user1");
UserImpl user2 = new UserImpl();
user2.setname("user2");
UserImpl user3 = new UserImpl();
user3.setname("user3");
UserImpl user4 = new UserImpl();
user4.setname("user4");
// register colleagues for chatroom1(mediator)
chatroom1.registerUser(user1);
chatroom1.registerUser(user2);
chatroom1.registerUser(user3);
// user1 sends message to chatroom1(mediator) users(colleagues)
user1.sendMessage(chatroom1, "hello from user1");
// create another mediator - chatroom2
ChatRoomeImpl chatroom2 = new ChatRoomeImpl("chatroom2");
// register colleagues for chatroom2(mediator)
chatroom2.registerUser(user3);
chatroom2.registerUser(user4);
// user3 sends message to chatroom1(mediator) users(colleagues)
user3.sendMessage(chatroom2, "hello from user3");
}

}

Output :

chatroom1 initialized
regestering new collegue user1
regestering new collegue user2
regestering new collegue user3
user2 received message : hello from user1
user3 received message : hello from user1
chatroom2 initialized
regestering new collegue user3
regestering new collegue user4
user4 received message : hello from user3

Wednesday, January 7, 2015

Iterator Design Pattern

Design Pattern > Behavioral Design Pattern > Iterator Design Pattern

The Intent of Iterator Design pattern is to trasverse through the elements of an aggregate object by passing it to Iterator.
Java Iterator is a nice implementation of iterator design pattern allowing us to traverse through a collection in a sequential way.

Benefits of Using Iterator Pattern :
Abstracting the details of the collection away from the task of sequentially traversing through the objects allows us to process any kind of collection without the tight coupling of having to know anything about the objects. This leads to cleaner and more readable code.

Iterator pattern is not all about traversing the collection of objects sequentially, you can modify/create new iterator to perform parallel iteration based on filtering as well.

Key Terms :
Iterator - 

  • An interface , declares methods for accessing and traversing elements

ConcreteIterator - 

  • Implements Iterator
  • Stores collection of elements ( passed in constructor )
  • Keeps track of current position in the traversal of Aggregate
  • Returns the next element in traversal

Aggregate - 

  • An Interface, declares methods to create Iterator object and to get collection of elements

ConcreteAggregete -

  • Implements Aggregate
  • Initialize collection of elements ( through constructor )
  • Return Iterator object
  • Return collection of elements

Client - 

  • Class to create Iterator object(s) by calling Agreegate's method to access elements.


Java Implementation :

/**
 *  Iterator interface
 */
package com.kmingle.iterator;

public interface Iterator {

Employee nextEmployee();
boolean isLastEmployee();
Employee currentEmployee();
}

/**
 * Concrete Iterator 
 */
package com.kmingle.iterator;

import java.util.List;


public class ContractEmployeeIterator implements Iterator {

public List employeeList;
private int position;
public ContractEmployeeIterator(List empList){
this.employeeList = empList;
}

@Override
public Employee nextEmployee() {
Employee emp = null;
for(; position < employeeList.size(); position++){
if("contractor".equals(((Employee) employeeList.get(position)).getEmpType())){
emp = (Employee) employeeList.get(position);
position++;
break;
}
}
return emp;
}


@Override
public boolean isLastEmployee() {
for(int i=position; i< employeeList.size();i++){
if("contractor".equals(((Employee) employeeList.get(i)).getEmpType())){
return false;
}
}
return true;
}


@Override
public Employee currentEmployee() {
if(position < employeeList.size()){
return (Employee) employeeList.get(position);
}
return null;
}

}


/**
 * Concrete Iterator 
 */
package com.kmingle.iterator;

import java.util.List;


public class PermanentEmployeeIterator implements Iterator {

public List employeeList;
private int position;
public PermanentEmployeeIterator(List empList){
this.employeeList = empList;
}

@Override
public Employee nextEmployee() {
Employee emp = null;
for(; position < employeeList.size(); position++){
if("permanent".equals(((Employee) employeeList.get(position)).getEmpType())){
emp = (Employee) employeeList.get(position);
position++;
break;
}
}
return emp;
}


@Override
public boolean isLastEmployee() {
for(int i=position; i< employeeList.size();i++){
if("permanent".equals(((Employee) employeeList.get(i)).getEmpType())){
return false;
}
}
return true;
}


@Override
public Employee currentEmployee() {
if(position < employeeList.size()){
return (Employee) employeeList.get(position);
}
return null;
}

}


/**
 * AggregateInterface
 */
package com.kmingle.iterator;

import java.util.List;

public interface Company {

List getEmployee();
void addEmployee(Employee emp);
void removeEmployee(Employee emp);
Iterator createIterator(String iteratorType);
}


/**
 * Concrete Aggregate
 */
package com.kmingle.iterator;

import java.util.ArrayList;
import java.util.List;


public class CompanyImpl implements Company {

List empList;
public CompanyImpl(){
empList = new ArrayList();
}
@Override
public List getEmployee() {
return empList;
}

@Override
public void addEmployee(Employee emp) {

empList.add(emp);
}

@Override
public void removeEmployee(Employee emp) {

empList.remove(emp);
}

@Override
public Iterator createIterator(String iteratorType) {

if("contractor".equals(iteratorType)){
return new ContractEmployeeIterator(empList);
}
else {
return new PermanentEmployeeIterator(empList);
}
}

}


/**
 * Client Class
 */
package com.kmingle.iterator;


public class IteratorDemo {

public static void main(String[] args) {

CompanyImpl company = new CompanyImpl();
company.addEmployee(new Employee("p1", "permanent"));
company.addEmployee(new Employee("c1", "contractor"));
company.addEmployee(new Employee("p2", "permanent"));
company.addEmployee(new Employee("p3", "permanent"));
company.addEmployee(new Employee("c2", "contractor"));
company.addEmployee(new Employee("p4", "permanent"));
Iterator contractIterator = company.createIterator("contractor");
while(!contractIterator.isLastEmployee()){
System.out.println("Contractor Employee : "+ contractIterator.nextEmployee().getEmpName());
}
Iterator permanentIterator = company.createIterator("permanent");
while(!permanentIterator.isLastEmployee()){
System.out.println("Permanent Employee : "+ permanentIterator.nextEmployee().getEmpName());
}
}

}

OutPut :

Contractor Employee : c1
Contractor Employee : c2
Permanent Employee : p1
Permanent Employee : p2
Permanent Employee : p3
Permanent Employee : p4



Total Pageviews