You are here
Home > Design >

Behavioral Design Patterns In Java

Behavioral Design Patterns In JavaIn continuation of the second part of Design Patterns in Java, we will discuss about Behavioral Design Patterns in Java in this article. We have already covered Creational Design Patterns in Java, and Structural Design Pattern in the first & the second part respectively. The Behavioral Design Patterns deal with better interaction between objects and to provide loose coupling and flexible design. Moreover, they use various techniques to make communication between objects easier.

We will discuss eleven design patterns in total in this article that come under the category of Behavioral Design Pattern. Let’s start discussing our topic ‘Behavioral Design Patterns In Java’.

What are Behavioral Design Patterns in Java?

Behavioral Design Patterns offer solution for the better interaction between objects and how to provide lose coupling and flexibility to extend easily.

What are the types of Behavioral Design Patterns in Java?

Following design patterns come under this category.

  1. Template Method Pattern
  2. Mediator Pattern
  3. Chain of Responsibility Pattern
  4. Observer Pattern
  5. Strategy Pattern
  6. Command Pattern
  7. State Pattern
  8. Visitor Pattern
  9. Iterator Pattern
  10. Interpreter Pattern
  11. Memento Pattern

Now, let’s understand each Design Pattern one by one.

Template Method Design Pattern

The Template Method Pattern describes 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.

We can use the Template Method pattern in situations when there is an algorithm, some steps of which could be implemented in multiple different ways. In such scenarios, the Template Method pattern suggests keeping the outline of the algorithm in a separate method referred to as a template method inside a class. We may refer to as a template class, leaving out the specific implementations of the variant portions (steps that can be implemented in multiple different ways) of the algorithm to different subclasses of this class.

The Template class does not necessarily have to leave the implementation to its subclasses entirety. Instead, as part of providing the outline of the algorithm, the Template class can also provide some amount of implementation that we can consider as invariant across different implementations. It can even provide default implementations for the variable parts, if appropriate. We only implement specific details inside different subclasses. This type of implementation eliminates the need for duplicate code, which means a minimum amount of code to be written.

Steps to Write code using the Template Method Pattern

  • Template method should consist of certain steps whose order is fixed and for some of the methods; implementation differs from base class to subclass. Template method should be final.
  • Most of the times, subclasses call methods from super class, but in template pattern, superclass template method calls methods of subclasses, this is known as Hollywood Principle“don’t call us, we’ll call you.”
  • Methods in the base class with default implementation are referred as Hooks and they are intended to be overridden by subclasses, if you want some of the methods to be not overridden, you can make them final, for example, in our case we can make doPack () method final because if we don’t want subclasses to override it.

Example

For example, let’s assume we book an order online. We will create one template PurchaseOrderTemplate as an abstract class and other classes as below. Moreover, even we can also declare it as an interface.

PurchaseOrderTemplate.java

public abstract class PurchaseOrderTemplate {

      public boolean isGift;
      public abstract void doSelect();
      public abstract void doPayment();
      public final void doPack(){
         System.out.println("Gift wrap done.");
      }
      public abstract void doDelivery();
      public final void processOrder() {
         doSelect();
         doPayment();
         // if(isGift){
           doPack();
         // }
         doDelivery();
      }
}

StorePurchaseOrder.java 

public class StorePurchaseOrder extends PurchaseOrderTemplate {

      @Override
      public void doSelect() {
         System.out.println("Customer chooses the item from self.");
      }

      @Override
      public void doPayment() {
         System.out.println("Pays at the counter through cash/card");
      }

      @Override
      public void doDelivery() {
         System.out.println("Item deliverd to in-delivery counter.");
      }
}

OnlinePurchaseOrder.java

public class OnlinePurchaseOrder extends PurchaseOrderTemplate {

      @Override
      public void doSelect() {
         System.out.println("Item added to online shopping cart,");
         System.out.println("Get gift wrap preference,");
         System.out.println("Get delivery address.");
      }

      @Override
      public void doPayment() {
         System.out.println("Online Payment through Netbanking/Cards.");
      }

      @Override
      public void doDelivery() {
         System.out.println("Ship the item through post to delivery address");
      }
}

TemplateMethodPatternTest.java

public class TemplateMethodPatternTest {

      public static void main(String[] args) {
         PurchaseOrderTemplate online= new OnlinePurchaseOrder();
         online.processOrder();
         PurchaseOrderTemplate offline= new StorePurchaseOrder();
         offline.processOrder();
      }
}

Output

Item added to online shopping cart,
Get gift wrap preference,
Get delivery address.
Online Payment through Netbanking/Cards.
Gift wrap done.
Ship the item through post to delivery address
Customer chooses the item from self.
Pays at counter through cash/card
Gift wrap done.
Item deliverd to in-delivery counter.

When to use the Template Design Pattern

  • To implement the invariant parts of an algorithm once and leave it up to subclasses to implement the behavior that can vary.
  • When common behavior among subclasses should be factored and localized in a common class to avoid code duplication. We should first identify the differences in the existing code and then separate the differences in new operations. Finally, replace the differing code with a template method that calls one of these new operations.

Usage in JDK

  • All non-abstract methods of java.io.InputStream, java.io.OutputStream, java.io.Reader and java.io.Writer. e.g. – java.io.InputStream#skip(), java.io.InputStream#read()
  • All non-abstract methods of java.util.AbstractList, java.util.AbstractSet and java.util.AbstractMap. e.g. – java.util.AbstractList#indexOf (), java.util.Collections#sort ().

Here, we have completed the first design pattern of our article ‘Behavioral Design Patterns In Java’.

 


Mediator Design Pattern

Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.

We use the Mediator Design Pattern to provide a centralized communication medium between different objects in a system.

Mediator pattern focuses on providing a mediator between objects for communication and help in implementing lose-coupling between objects. Objects ask the Mediator to interact on their behalf, rather than interacting directly with each other. It results in reusability and loose coupling. Furthermore, It encapsulates the interaction between the objects and makes them independent from each other. This also allows them to vary their interaction with other objects in a totally different way by implementing a different mediator. The Mediator helps to reduce the complexity of the classes. Moreover, each object no longer has to know in detail about how to interact with the other objects. The coupling between objects goes from tight and rigid to loosen and graceful.

The Mediator design pattern is very helpful in an enterprise application where multiple objects are interacting with each other. If the objects interact with each other directly, the system components become tightly-coupled with each other. They also make the maintainability cost higher and not flexible to extend easily.

For example, the Air traffic controller is a great example of mediator pattern where the airport control room works as a mediator for communication between different flights. The mediator works as a router between objects and it can have its own logic to provide way of communication.

Participants in Mediator Pattern

The major participants of the Mediator Pattern are:

  • Mediator: Defines an interface for communicating with Colleague objects.
  • ConcreteMediator: Implements cooperative behavior by coordinating Colleague objects. It also knows and maintains its colleagues.
  • Colleague Classes: Each Colleague class knows its Mediator objects. Each colleague communicates with its mediator whenever it would have otherwise communicated with another colleague.

Example

For example, let’s consider a Mediator interface as IMediator.

IMediator.java

Colleague A wants to talk, and Colleague B wants to fight with the mediator. When they do some action (i.e., doSomething()), they invoke mediator to do that.

public interface IMediator {

      public void talk();
      public void fight();
      public void registerA(ColleagueA a);
      public void registerB(ColleagueB b);
}

ConcreteMediator.java 

public class ConcreteMediator implements IMediator {

      ColleagueA talk;
      ColleagueB fight;

      @Override
      public void talk() {
      System.out.println("Mediator is talking");
      //let the talk colleague do some stuff
      }

      @Override
      public void fight() {
         System.out.println("Mediator is fighting");
      //let the fight colleague do some stuff
      }

      @Override
      public void registerA(ColleagueA a) {
         this.talk=a;
      }

      @Override
      public void registerB(ColleagueB b) {
         this.fight=b;
      }
}

Colleague.java

public abstract class Colleague {
      IMediator mediator;
      public abstract void doSomething();
}

ColleagueA.java

public class ColleagueA extends Colleague {

      public ColleagueA(IMediator mediator) {
         this.mediator= mediator;
         this.mediator.registerA(this);
      }

      @Override
      public void doSomething() {
         this.mediator.talk();
      }
}

ColleagueB.java

public class ColleagueB extends Colleague {

      public ColleagueB(IMediator mediator) {
         this.mediator=mediator;
         this.mediator.registerB(this);
      }

      @Override     
      public void doSomething() {
         this.mediator.fight();
      }
}

MediatorPatternTest.java

public class MediatorPatternTest {

      public static void main(String[] args) {
         IMediator mediator = new ConcreteMediator();

         ColleagueA talkColleague= new ColleagueA(mediator);
         talkColleague.doSomething();

         ColleagueB fightColleague = new ColleagueB(mediator);
         fightColleague.doSomething();
      }
}

Output

Mediator is talking
Mediator is fighting

When to use the Mediator Pattern

  1. A set of objects communicates in well-defined but complex ways. The resulting interdependencies are unstructured and difficult to understand.
  2. Reusing an object is difficult because it refers to and communicates with many other objects.
  3. A behavior that’s distributed between several classes should be customizable without a lot of sub-classing.

Mediator Pattern in JDK

  • util.Timer class scheduleXXX () methods.
  • Java Concurrency Executor execute () method.
  • lang.reflect.Method invoke () method.

Here, we have completed the second design pattern of our article ‘Behavioral Design Patterns In Java’.

 


Behavioral Design Patterns In JavaChain Of Responsibility Design Pattern

When there are more than one objects that can handle or fulfill a client request, the pattern recommends giving each of these objects a chance to process the request in some sequential order. Applying the pattern in such a case, each of these potential handlers can be arranged in the form of a chain, with each object having a reference to the next object in the chain.

The first object in the chain receives the request and decides either to handle the request or to pass it on to the next object in the chain. The request flows through all objects in the chain one after the other until the request is handled by one of the handlers in the chain or the request reaches the end of the chain without getting processed.

Obviously, the Chain of responsibility pattern is used to achieve loose coupling in software design where a request from a client is passed to a chain of objects to process them. Then the object in the chain will decide themselves who will be processing the request and whether the request is required to be sent to the next object in the chain or not.

Example

For example, we know exception handling better than anybody else and we are daily living with it. This qualifies as the best example for chain of responsibility. Let’s see the example of the chain of responsibility pattern in JDK and then we will proceed to implement a real life example of this pattern.

We know that we can have multiple catch blocks in a try-catch block code. Here every catch block is kind of a processor to process that particular exception. So, when any exception occurs in the try block it is sent to the first catch block to process. If that catch block is not able to process it, it forwards the request to the next object in chain i.e. next catch block. If even the last catch block is not able to process it, the exception is thrown outside of the chain to the calling program.

Other examples are ATM money dispenser, Servlet Filter mechanism. In ATM Dispense machine, the user enters the amount to be dispensed and the machine dispense amount in terms of defined currency bills such as 50$, 20$, 10$ etc. If the user enters an amount that is not multiples of 10, it throws error.

Now let’s consider a real life example of Number system programmatically.

Number.java

//This class is the request object.
public class Number {

       private int number;

       public int getNumber() {
          return number;
       }

       public Number(int num){
          number=num;
       }
}

Chain.java

//This is the interface that acts as a chain link.
public interface Chain {
      public void setNext(Chain nextInChain);
      public void process(Number request);
}

PositiveNumberProcessor.java

public class PositiveNumberProcessor implements Chain {

      private Chain nextInChain;

      @Override
      public void setNext(Chain c) { 
         nextInChain = c;
      }

      @Override
      public void process(Number request) {

      if (request.getNumber() > 0) {
            System.out.println("PositiveNumberProcessor : " + request.getNumber());
         } else {
            nextInChain.process(request);
         }
     }
}

NegativeNumberProcessor.java

public class NegativeNumberProcessor implements Chain {

      private Chain nextInChain;

      @Override
      public void setNext(Chain c) {
         nextInChain=c;
      }

      @Override
      public void process(Number request) {

         if (request.getNumber() < 0) {
             System.out.println("NegativeNumberProcessor : " + request.getNumber());
         } else {
             nextInChain.process(request);
         }
      }
}

ZeroProcessor.java

public class ZeroProcessor implements Chain {

      private Chain nextInChain;

      @Override
      public void setNext(Chain c) {
         nextInChain = c;
      }

      @Override
      public void process(Number request) {

         if (request.getNumber() == 0) {
            System.out.println("ZeroProcessor : " + request.getNumber());
         } else {
            nextInChain.process(request);
         }
      }
}

CORPatternTest.java

public class CORPatternTest {

      public static void main(String[] args) {

      //configure Chain of Responsibility
         Chain c1 = new NegativeNumberProcessor();
         Chain c2 = new ZeroProcessor();
         Chain c3 = new PositiveNumberProcessor();
         c1.setNext(c2);
         c2.setNext(c3);

     //calling chain of responsibility
         c1.process(new Number(99));
         c1.process(new Number(-30));
         c1.process(new Number(0));
         c1.process(new Number(100));
      }
}

Output

PositiveNumberProcessor : 99
NegativeNumberProcessor : -30
ZeroProcessor : 0
PositiveNumberProcessor : 100

When to use the Chain of Responsibility Pattern

Use Chain of Responsibility when

  1. More than one object may handle a request, and the handler isn’t known a priori. The handler should be ascertained automatically.
  2. You want to issue a request to one of several objects without specifying the receiver explicitly.
  3. The set of objects that can handle a request should be specified dynamically.

Chain of Responsibility Pattern Examples in JDK

  • util.logging.Logger#log ()
  • servlet.Filter#doFilter ()

Here, we have completed the third design pattern of our article ‘Behavioral Design Patterns In Java’.

 


Observer Design Pattern

In observer design pattern multiple observer objects registers with a subject for any change in notification. When the state of subject changes, it notifies the observers. Objects that listen or watch for change are called observers and the object that is being watched is called a subject.

Pattern involved is also called as publish-subscribe pattern.

  • The subject provides an interface for observers to register and unregister themselves with the subject.
  • The subject knows who its subscribers are.
  • Multiple observers can subscribe for notifications.
  • Subject publishes the notifications.
  • The Subject just sends the notification saying the state has changed. It does not pass any state information.
  • Once the notification is received from subject, observers call the subject and get data that is changed.

The above last two points are not strictly followed in observer design pattern implementation. Along with the notification, state is also passed in some implementation so that the observer need not query back to know the status. It is better not to do this way.

Participants in the Observer Pattern

There are four participants in the Observer pattern:

  1. Subject,  to register observers. Objects use this interface to register as observers and also to remove themselves from being observers.
  2. Observer defines an updating interface for objects that should be notified of changes in a subject. However, All observers need to implement the Observer interface. This interface has a method update (), which gets called when the Subject’s state changes.
  3. ConcreteSubject stores the state of interest to ConcreteObserver objects. It sends a notification to its observers when its state changes. Further, A concrete subject always implements the Subject interface. We use the notifyObservers() method to update all the current observers whenever the state changes.
  4. ConcreateObserver maintains a reference to a ConcreteSubject object and implements the Observer interface. Each observer registers with a concrete subject to receive updates.

Java provides inbuilt platform for implementing Observer pattern through java.util.Observable class and java.util.Observer interface. However, we don’t use it widely because the implementation is really simple and most of the times, we don’t want to end up extending a class just for implementing Observer pattern as java doesn’t provide multiple inheritances in classes.

Example

Let’s take a blog and subscriber example for observer design pattern as a sample implementation. Assume that there is a blog and users register to that blog for update. When a new article is posted in the blog, it will send update to the registered users saying a new article is available. Then the user will access the blog and read the new article posted. In this example, blog is the subject and users are the observers.

Subject.java

public interface Subject {

      public void registerObserver(Observer observer);
      public void notifyObserver();
      public void unregisterObserver(Observer observer);
      public Object getUpdate();
}

Observer.java

public interface Observer {

      public void update();
      public void setSubject(Subject sub);
}

Blog.java

//Concrete Subject
public class Blog implements Subject {

      List<Observer> observersList;
      private boolean stateChange;

      public Blog() {
         this.observersList = new ArrayList();
         stateChange = false;
      }

      @Override
      public void registerObserver(Observer observer) {
         observersList.add(observer);
      }

      @Override
      public void notifyObserver() {
         if (stateChange) {
           for(Observer observer : observersList) {
              observer.update();
              System.out.println("Observer notified !");
           }
         }
      }

      @Override
      public void unregisterObserver(Observer observer) {
         observersList.remove(observer);
      }

      @Override
      public Object getUpdate() {
         Object changedState = null;
         // should have logic to send the state change to querying observer
         if (stateChange) {
           changedState = "Observer Design Pattern";
         }
       return changedState;
      }

      public void postNewArticle() {
         stateChange = true;
         notifyObserver();
      }
}

User.java

//Concrete Observer
public class User implements Observer {

      private String article;
      private Subject blog; 
      
      @Override
      public void update() {
         System.out.println("State change reported by Subject.");
         article = (String) blog.getUpdate();
      }

      @Override
      public void setSubject(Subject blog) {
         this.blog = blog;
         article = "No New Article!";
      }

      public String getArticle() {
         return article;
      }
}

ObserverPatternTest.java

public class ObserverPatternTest {

      public static void main(String[] args) {
         Blog blog = new Blog();
         User user1 = new User();
         User user2 = new User();
         blog.registerObserver(user1);
         blog.registerObserver(user2);
         user1.setSubject(blog);
         user2.setSubject(blog);
         System.out.println(user1.getArticle()); 
         blog.postNewArticle();
         System.out.println(user1.getArticle());
      }
}

Output

No New Article!
State change reported by Subject.
Observer notified !
State change reported by Subject.
Observer notified !
Observer Design Pattern

When to use the Observer Pattern

Use the Observer pattern in any of the following situations:

  1. When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.
  2. When a change to one object requires changing others, and you don’t know how many objects need to be changed?
  3. When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don’t want tight coupling in these objects.

Usage in Java

  • util.EventListener in Swing
  • servlet.http.HttpSessionBindingListener
  • servlet.http.HttpSessionAttributeListener

Here, we have completed the fourth design pattern of our article ‘Behavioral Design Patterns In Java’.

 


Strategy Design Pattern

The Strategy Design Pattern is useful when there is a set of related algorithms and a client object needs to be able to dynamically pick and choose an algorithm from this set that suits its current need. The Strategy pattern suggests keeping the implementation of each of the algorithms in a separate class. Each such algorithm encapsulated in a separate class is referred to as a Strategy. An object that uses a Strategy object is often referred to as a context object.

We use Strategy Pattern when we have multiple algorithms for a specific task and client decides the actual implementation to be used at runtime. The Strategy Pattern is also known as Policy Pattern. We define multiple algorithms and let the client application pass the algorithm to be used as a parameter. For example, one of the best examples of this pattern is Collections.sort () method that takes Comparator parameter. Based on the different implementations of Comparator interfaces, the Objects are getting sorted in different ways.

The Strategy Pattern is one way where we can use composition as an alternative to sub-classing. Rather than providing different behaviors via subclasses overriding methods in super classes, the strategy pattern allows different behaviors to be placed in Concrete Strategy classes which share the common Strategy interface. A Context object contains a reference to a Strategy. By changing the Context’s Strategy, we can obtain the different behaviors.

Example

For example, let’s consider below Java Program to implement Strategy Design Pattern in Java. As aforementioned, you should consider using this pattern when you need to select an algorithm at runtime. We will take an example of various sorting algorithms available as part of our data structure subject. We will observe how the client can choose any algorithm at run time. Also, we can easily add new Strategy without modifying classes which uses strategies e.g. Context.

However, this becomes possible because Strategy pattern is based upon the Open Closed Design Principle, which says that new behavior is added by writing new code not by modifying tried and tested old code. If you use Strategy pattern, you will be adding a new Strategy by writing a new class which just needs to implement the Strategy interface.

Strategy.java

public interface Strategy {

      public void sort(int [] numbers);
}

Context.java

public class Context {

      private Strategy strategy;

      public Context(Strategy strategy){
         this.strategy=strategy;
      }

      public void arrange(int [] input){
         strategy.sort(input);
      }
}

BubbleSort.java

public class BubbleSort implements Strategy {

      @Override
      public void sort(int[] numbers) {
         System.out.println("sorting array using bubble sort strategy");
      }
}

InsertionSort.java

public class InsertionSort implements Strategy {

      @Override
      public void sort(int[] numbers) {
         System.out.println("sorting array using insertion sort strategy");
      }
}

MergeSort.java

public class MergeSort implements Strategy {

      @Override
      public void sort(int[] numbers) {
         System.out.println("sorting array using merge sort strategy");
      }
}

QuickSort.java

public class QuickSort implements Strategy {

      @Override
      public void sort(int[] numbers) {
         System.out.println("sorting array using quick sort strategy");
      }
}

StrategyPatternTest.java

public class StrategyPatternTest {

      public static void main(String[] args) {

      int[] nums= {6, 9, 7, 4, 8};

       //We can provide any strategy to do the sorting
      Context ctx = new Context(new BubbleSort());
      ctx.arrange(nums);

       //We can change the strategy without changing Context class
      ctx = new Context(new QuickSort()); 
      ctx.arrange(nums);
      }
}

Output

sorting array using bubble sort strategy
sorting array using quick sort strategy

When to use the Strategy Design Pattern

Use the Strategy pattern when:

  • Many related classes differ only in their behavior as Strategies provide a way to configure a class with one of many behaviors.
  • You need different variants of an algorithm. For example, you might define algorithms reflecting different space/time trade-offs. Here, we can use Strategies when the implementation of these variants are as a class hierarchy of algorithms.
  • An algorithm uses data that clients shouldn’t know about. Use the Strategy pattern to avoid exposing complex, algorithm-specific data structures.
  • A class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move related conditional branches into their own Strategy class.

Strategy Pattern in JDK

  • util.Comparator#compare ()
  • servlet.http.HttpServlet
  • servlet.Filter#doFilter ()

Here, we have completed the fifth design pattern of our article ‘Behavioral Design Patterns In Java’.

 


Command Design Pattern

The Command Pattern is a behavioral object design pattern. In the command pattern, a Command interface declares a method for executing a particular action. Concrete Command classes implement the execute () method of the Command interface, and this execute () method invokes the appropriate action method of a Receiver class that the Concrete Command class contains.

Further, the Receiver class performs a particular action. However, a Client class is responsible for creating a Concrete Command and setting the Receiver of the Concrete Command. Moreover, an Invoker class contains a reference to a Command and has a method to execute the Command.

In the command pattern, the invoker is decoupled from the action performed by the receiver. The invoker has no knowledge of the receiver. The invoker invokes a command, and the command executes the appropriate action of the receiver. Thus, the invoker can invoke commands without knowing the details of the action to be performed. In addition, this decoupling means that changes to the receiver’s action don’t directly affect the invocation of the action.

We can even use the command pattern to perform ‘undo’ functionality. In this case, the Command interface should include a method such as unexecuted () method.

Needless to say, it also helps us to achieve loose coupling in a request-response model. In a nutshell, the request is sent to the invoker and invoker passes it to the encapsulated command object. The command object passes the request to the appropriate method of Receiver to perform the specific action. The client program creates the receiver object and then attaches it to the Command. Then, it creates the invoker object and attaches the command object to perform an action. Now, when client program executes the action, it’s processed based on the command and receiver object.

Associated terms in the Command Pattern

To understand the Command Design Pattern, we should understand the associated key terms like client, command, command implementation, invoker, and receiver.

  • Command is an interface with execute() method. It is the core of contract.
  • The Client creates an instance of a command implementation and associates it with a receiver.
  • An Invoker instructs the command to perform an action.
  • Command implementation’s instance creates a binding between the receiver and an action.
  • Receiver is the object that knows the actual steps to perform the action. Any class may serve as a Receiver.

Example

For example, Let’s understand Command Pattern by making Lunch, Dinner & Meal programmatically.

Command.java

/**
Command interface with an execute() method.
*/
public interface Command {

      public void execute();
}

Lunch.java

/**
Lunch is a receiver.
*/
public class Lunch {

      public void makeLunch(){
         System.out.println("Lunch is being made");
      }
}

LunchCommand.java

/**
LunchCommand implements Command. It contains a reference to Lunch, a receiver.
Its execute() method invokes the appropriate action on the receiver.
*/
public class LunchCommand implements Command {

      Lunch lunch;

      public LunchCommand(Lunch lunch) {
         this.lunch = lunch;
      }

      @Override
      public void execute() {
         lunch.makeLunch();
      }
}

Dinner.java

/**
Dinner is also a receiver.
*/
public class Dinner {
      public void makeDinner(){
         System.out.println("Dinner is being made.");
      }
}

DinnerCommand.java

/**
The DinnerCommand is similar to LunchCommand.
It contains a reference to Dinner, a receiver.
Its execute() method invokes the makeDinner() action of the Dinner object.
*/
public class DinnerCommand implements Command {

      Dinner dinner;

      public DinnerCommand(Dinner dinner){
         this.dinner=dinner;
      }

      @Override
      public void execute() {
         dinner.makeDinner();
      }
}

MealInvoker.java

/**
MealInvoker is the invoker class.
It contains a reference to the Command to invoke.
Its invoke() method calls the execute() method of the Command.
*/
public class MealInvoker {

      Command command;

      public MealInvoker(Command command) {
         this.command = command;
      }

      public void setCommand(Command command) {
         this.command = command;
      }

      public void invoke() {
         command.execute();
      }
}

CommandPatternTest.java

public class CommandPatternTest {

      public static void main(String[] args) {

         Lunch lunch = new Lunch(); // receiver
         Command lunchCommand = new LunchCommand(lunch); // concrete command

         Dinner dinner = new Dinner(); // receiver
         Command dinnerCommand = new DinnerCommand(dinner); // concrete command

         MealInvoker mealInvoker = new MealInvoker(lunchCommand); // invoker
         mealInvoker.invoke();

         mealInvoker.setCommand(dinnerCommand);
         mealInvoker.invoke();
      }
}

Output

Lunch is being made
Dinner is being made.

When to use the Command Design Pattern

Use the Command pattern when you want to:

  • Parameterize objects by an action to perform.
  • Structure a system around high-level operations built on primitives’ operations. Such a structure is common in information systems that support transactions. Moreover, the Command Pattern offers a way to model transactions. Commands have a common interface, letting you invoke all transactions the same way. The pattern also makes it easy to extend the system with new transactions.
  • The Command’s Execute operation can store state for reversing its effects in the command itself. The Command interface must have an added Un-execute operation that reverses the effects of a previous call to Execute. We can store the executed commands  in a history list. Also, we can achieve Unlimited-level undo and redo by traversing this list backwards and forwards calling Un-execute and Execute, respectively. It supports undo as well.

Command Pattern JDK Example

Runnable interface (java.lang.Runnable) and Swing Action (javax.swing.Action) uses command pattern.

Here, we have completed the sixth design pattern of our article ‘Behavioral Design Patterns In Java’.

 


Visitor Design Pattern

When we have to perform an operation on a group of similar kind of Objects, we use Visitor Pattern. With the help of visitor pattern, we can move the operational logic from the objects to another class. For example, think of a Shopping cart where we can add different type of items (Elements), when we click on the checkout button, it calculates the total amount that we need to pay. Now, we can have the calculation logic in item classes or we can move out this logic to another class using Visitor Pattern. So, using visitor pattern we can move out logics to another class.

The Visitor Pattern allows the operation to be defined without changing the class of any of the objects in the collection. To accomplish this, the Visitor pattern suggests defining the operation in a separate class referred to as a visitor class. This separates the operation from the object collection that it operates on. For every new operation to be defined, a new visitor class is created. Since the operation is to be performed across a set of objects, the visitor needs a way of accessing the public members of these objects.

Components involved in Visitor Pattern

Visitor: Declares a Visit operation for each class of ConcreteElement in the object structure. The operation’s name and signature identify the class that sends the Visit request to the visitor. That lets the visitor determine the concrete class of the element being visited. Then the visitor can access the element directly through its particular interface.

ConcreteVisitor: Implements each operation declared by the Visitor. Each operation implements a fragment of the algorithm defined for the corresponding class of object in the structure. ConcreteVisitor provides the context for the algorithm and stores its local state. This state often accumulates results during the traversal of the structure.

Element: Defines an Accept operation that takes a visitor as an argument.

ConcreteElement: Implements an Accept operation that takes a visitor as an argument.

ObjectStructure:

  • Can enumerate its elements.
  • May provide a high-level interface to allow the visitor to visit its elements.
  • May either be a composite or a collection such as a list or a set.

Example

For example, in order to implement Visitor Pattern, first of all we create different type of items (Elements) that we will use in shopping cart.

ShoppingCartElement.java

Notice that accept method takes Visitor argument. We can have some other methods also specific for items, but for simplicity, we will not go into too much detail, instead focus on Visitor Pattern only.

public interface ShoppingCartElement {

      public int accept(ShoppingCartVisitor visitor);
}

Book.java

public class Book implements ShoppingCartElement {

      private int price;
      private String isbnNumber;

      public Book(int cost, String isbn){
         this.price=cost;
         this.isbnNumber=isbn;
      }

      public int getPrice() {
         return price;
      }

      public String getIsbnNumber() {
         return isbnNumber;
      }

      @Override
      //Notice the implementation of accept() method in concrete classes, 
      //its calling visit() method of Visitor and passing itself as argument.
      public int accept(ShoppingCartVisitor visitor) {
         return visitor.visit(this);
      }
}

Fruit.java

public class Fruit implements ShoppingCartElement {

      private int pricePerKg;
      private int weight;
      private String name;

      public Fruit(int priceKg, int wt, String name){
         this.pricePerKg=priceKg;
         this.weight=wt;
         this.name = name;
      }

      public int getPricePerKg() {
         return pricePerKg;
      }

      public int getWeight() {
         return weight;
      }

      public String getName(){
         return name;
      }

      @Override
      public int accept(ShoppingCartVisitor visitor) {
         return visitor.visit(this);
      }
}

ShoppingCartVisitor.java

We will have visit() method for different type of items in Visitor interface, that we can implement by concrete visitor class.

public interface ShoppingCartVisitor {

      int visit(Book book);
      int visit(Fruit fruit);
}

ShoppingCartVisitorImpl.java

Now we will implement the visitor interface and every item will have its own logic to calculate the cost.

public class ShoppingCartVisitorImpl implements ShoppingCartVisitor {

      @Override
      public int visit(Book book) {
         int cost=0;
         //apply 5$ discount if book price is greater than 50
         if(book.getPrice() > 50){
            cost = book.getPrice()-5;
         }else 
            cost = book.getPrice();
         System.out.println("Book ISBN::"+book.getIsbnNumber() + " cost ="+cost);
         return cost;
      }

      @Override
      public int visit(Fruit fruit) {
         int cost = fruit.getPricePerKg()*fruit.getWeight();
         System.out.println(fruit.getName() + " cost = "+cost);
         return cost;
      }
}

VisitorPatternTest.java

public class VisitorPatternTest {

      public static void main(String[] args) {

         ShoppingCartElement[] items = new ShoppingCartElement[]{new Book(20, "1234"),
         new Book(100, "5678"),
         new Fruit(10, 2, "Banana"), new Fruit(5, 5, "Apple")};

         int total = calculatePrice(items);
         System.out.println("Total Cost = "+total);
      }

      private static int calculatePrice(ShoppingCartElement[] items) {

         ShoppingCartVisitor visitor = new ShoppingCartVisitorImpl();
         int sum=0;
         for(ShoppingCartElement item : items){
             sum = sum + item.accept(visitor);
         }
         return sum;
      }
}

Output

Book ISBN::1234 cost =20
Book ISBN::5678 cost =95
Banana cost = 20
Apple cost = 25
Total Cost = 160

The main benefit of this pattern is that if the logic of operation changes, then we need to make changes only in the visitor implementation rather than doing it in all the item classes

When to use the Visitor Design Pattern

Use the Visitor pattern when:

  • An object structure contains many classes of objects with differing interfaces, and you want to perform operations on these objects that depend on their concrete classes.
  • When we need to perform many distinct and unrelated operations on objects in an object structure, and we want to avoid “polluting” their classes with these operations. Visitor lets you keep related operations together by defining them in one class. When we need to share the object structure with many applications, use Visitor to put operations in just those applications that need them.
  • The classes defining the object structure rarely change, but you often want to define new operations over the structure. However, changing the object structure classes requires redefining the interface to all visitors, which is potentially costly. If the object structure classes change often, then it’s probably better to define the operations in those classes.

Visitor Design Pattern in JDK

  • lang.model.element.Element and javax.lang.model.element.ElementVisitor
  • lang.model.type.TypeMirror and javax.lang.model.type.TypeVisitor

Here, we have completed the seventh design pattern of our article ‘Behavioral Design Patterns In Java’.

 


State Design Pattern

We use State Design Pattern when an Object changes its behavior on change of its internal state. We can define the state of an object as its exact condition at any given point of time, depending on the values of its properties or attributes. The set of methods implemented by a class constitutes the behavior of its instances. Whenever there is a change in the values of its attributes, we say that the state of an object has changed.

When a Context object is first created, it initializes itself with its initial State object. This State object becomes the current State object for the context. By replacing the current State object with a new State object, the context transitions to a new state. When an application object makes a call to a Context method (behavior), it forwards the method call to its current State object.

Context: Defines the interface of interest to clients. Moreover, it maintains an instance of a ConcreteState subclass that defines the current state.

StateDefines an interface for encapsulating the behavior associated with a particular state of the Context.

ConcreteState subclasses: Each subclass implements a behavior associated with a state of the Context.

In the State Pattern, we have a Context class, and this class has a State reference to a Concrete State instance. The State interface declares particular methods that represent the behaviors of a particular state. Concrete States implement these behaviors. By changing a Context’s Concrete State, we change its behavior. In essence, in the state pattern, a class (the Context) is supposed to behave like different classes depending on its state. The state pattern avoids the use of switch and if statements to change behavior.

Example

For example, let’s implement an example of different states of a Mobile using State Design Pattern.

MobileState.java

public interface MobileState {

      public void getState();
}

Ringing.java

public class Ringing implements MobileState {

      @Override
      public void getState() {
         System.out.println("Mobile is in ringing state");
      }
}

Silent.java

public class Silent implements MobileState {

      @Override
      public void getState() {
         System.out.println("Mobile is in silent state");
      }
}

Vibration.java

public class Vibration implements MobileState {

      @Override
      public void getState() {
         System.out.println("Mobile is in vibration state");
      }
}

MobileContext.java

public class MobileContext implements MobileState {

      private MobileState mobileState;

      public void setMobileState(MobileState state) {
         mobileState=state;
      }

      public MobileContext(MobileState mobileState){
         this.mobileState= mobileState;
      }

      public void getState(){
         mobileState.getState();
      }
}

StatePatternTest.java

public class StatePatternTest {

      public static void main(String[] args) {
         MobileContext ctx = new MobileContext(new Ringing());
         ctx.getState();
         ctx.getState();
         ctx.setMobileState(new Vibration());
         ctx.getState();
         ctx.getState();
         ctx.getState();
         ctx.setMobileState(new Silent());
         ctx.getState();
         ctx.getState();
      }
}

Output

Mobile is in ringing state
Mobile is in ringing state
Mobile is in vibration state
Mobile is in vibration state
Mobile is in vibration state
Mobile is in silent state
Mobile is in silent state

In fact, one of the benefit of using State pattern is the implementation of polymorphic behavior, which is clearly visible. Hence, the chances of error are less. Also, it’s very easy to add more states for additional behavior that makes it more robust, easily maintainable and flexible. In addition, State Pattern helped in avoiding if-else or switch-case conditional logic in this scenario.

When to use the State Design Pattern

Use the State pattern in either of the following cases:

  • When an object’s behavior depends on its state, and it must change its behavior at run-time depending on its state.
  • When operations have large, multipart conditional statements that depend on the object’s state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State Pattern puts each branch of the conditional in a separate class. This lets us treat the object’s state as an object in its own right that can vary independently from other objects.

State Design Pattern in Java

  • faces.lifecycle.LifeCycle#execute()

Here, we have completed the eighth design pattern of our article ‘Behavioral Design Patterns In Java’.

 


Iterator Design Pattern

Iterator Pattern in one of the behavioral patterns and we use it to provide a standard way to traverse through a group of Objects. We widely use the Iterator Pattern in Java Collection Framework where Iterator interface provides methods for traversing through a collection.

The logic for iteration is embedded in the collection itself and it helps client program to iterate over them easily. An Iterator object contains public methods to allow a client object to navigate through the list of objects within the container.

Components in the Iterator Pattern

Iterator

  • Defines an interface for accessing and traversing elements.

ConcreteIterator

  • Implements the Iterator interface.
  • Keeps track of the current position in the traversal of the aggregate.

Aggregate

  • Defines an interface for creating an Iterator object.

ConcreteAggregate

  • Implements the Iterator creation interface to return an instance of the proper ConcreteIterator.

When to use the Iterator Design Pattern

Use the Iterator pattern:

  • When you want to provide a standard way to iterate over a collection and hide the implementation logic from client program.
  • When you need to access an aggregate object’s contents without exposing its internal representation.
  • To support multiple traversals of aggregate objects.
  • To provide a uniform interface for traversing different aggregate structures (that is, to support polymorphic iteration).

Iterator Pattern in JDK

  • util.Iterator
  • util.Enumeration

Here, we have completed the ninth design pattern of our article ‘Behavioral Design Patterns In Java’.

 


Interpreter Design Pattern

Interpreter Pattern is one of the behavioral design patterns and we use it to define a grammatical representation for a language and it provides an interpreter to deal with the grammar. The best example of this pattern is java compiler that interprets the java source code into byte code that is understandable by JVM. Google Translator is also an example of interpreter pattern where the input can be in any language and we can get the interpreted output in another language.

In order to implement the Interpreter Pattern, we need to create Interpreter context engine that will do the interpretation work. Then, we need to create different Expression implementations that will consume the functionalities provided by the interpreter context. Finally, we need to create the client that will take the input from user and decide which Expression to use and then generate output for the user.

When to use the Interpreter Design Pattern

Use the Interpreter pattern when there is a language to interpret, and you can represent statements in the language as abstract syntax trees. The Interpreter pattern works best when

  • The grammar is simple. For complex grammars, the class hierarchy for the grammar becomes large and unmanageable. Tools such as parser generators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can save space and possibly time also.
  • Efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then, we can implement the translator with the help of Interpreter pattern, so the pattern is still applicable.

Interpreter Design Pattern in JDK

  • util.Pattern
  • text.Normalizer
  • text.Format

Here, we have completed the tenth design pattern of our article ‘Behavioral Design Patterns In Java’.

 


Memento Design Pattern

Memento pattern is one of the behavioral design patterns. We use Memento Design Pattern when we want to save the state of an object so that we can restore it later on. Memento pattern helps to implement this in such a way that the saved state data of the object is not accessible outside of the object; this protects the integrity of saved state data.

The idea of implementing Memento pattern starts with with two objects – Originator and Caretaker. Originator is the object whose state needs to be saved and restored and it uses an inner class to save the state of Object. The inner class is called Memento and its private, so that it can’t be accessed from other objects.

Caretaker is the helper class that is responsible for storing and restoring the Originator’s state through Memento object. Since Memento is private to Originator, Caretaker can’t access it and it’s stored as an Object within the caretaker.

One of the best real-life examples is the text editors where we can save its data anytime and use undo to restore it to previous saved state.

When to use the Memento Pattern

Use the Memento Pattern in the following cases:

  • A snapshot of (some portion of) an object’s state must be saved so that it can be restored to that state later, and
  • A direct interface to obtain the state would expose implementation details and break the object’s encapsulation.

Memento Pattern in JDK

  • java.util.Date
  • java.io.Serializable

Here, we have completed the last design pattern of our article ‘Behavioral Design Patterns In Java’.

Links to Other Design Patterns 

Creational Design Patterns

Structural Design Patterns

 


 

 

 

Leave a Reply


Top