Monday, November 2, 2015

Design Patterns - Chain Of Responsibility




Links for reading:

http://javapapers.com/design-patterns/chain-of-responsibility-design-pattern/
https://dzone.com/articles/design-patterns-uncovered-chain-of-responsibility

Copying information from Above here...


Chain of responsibility is a design pattern where a sender sends a request to a chain of objects, where the objects in the chain decide themselves who to honor the request. If an object in the chain decides not to serve the request, it forwards the request to the next object in the chain.


  • Sender will not know which object in the chain will serve its request.
  • Every node in chain will have the responsibility to decide, if they can serve the request.
  • If node decides to forward the request, it should be capable of choosing the next node and forward it.
  • There is a possibility where none of the node may serve the request.
Example: 
1. Exception Handling
2. Servlet Filters
3. java.util.Logging
4. Typical Finance Dept (Associate --> Manager --> Director Budget approval)

There may be scenarios where a node is capable of solving the request but may not get a chance for it. Though there is a candidate who can solve the problem, but since nobody forwarded the request to it, it was not given a chance to serve and final result is the request goes unattended failure. This happens because of improper chain sequence. A chain sequence may not be suitable for all scenarios.


In object oriented design generally, every object is responsible for all its behavior. Behavior of an object is not transferred to other objects and is enclosed within itself. In chain of responsibility, some percentage of behavior is offloaded to third party objects.


Example - 1

Chain.java

This is the interface that acts as a chain link.
package com.javapapers.designpattern.chainofresponsibility;

public interface Chain {

 public abstract void setNext(Chain nextInChain);
 public abstract void process(Number request);
}

Number.java

This class is the request object.
package com.javapapers.designpattern.chainofresponsibility;

public class Number {
 private int number;

 public Number(int number) {
  this.number = number;
 }

 public int getNumber() {
  return number;
 }

}

NegativeProcessor.java

This class is a link in chain series.
package com.javapapers.designpattern.chainofresponsibility;

public class NegativeProcessor implements Chain {

 private Chain nextInChain;

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

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

ZeroProcessor.java

This class is another link in chain series.
package com.javapapers.designpattern.chainofresponsibility;

public class ZeroProcessor implements Chain {

 private Chain nextInChain;

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

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

PositiveProcessor.java

This class is another link in chain series.
package com.javapapers.designpattern.chainofresponsibility;

public class PositiveProcessor implements Chain {

 private Chain nextInChain;

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

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

TestChain.java

This class configures the chain of responsibility and executes it.
package com.javapapers.designpattern.chainofresponsibility;

public class TestChain {
 public static void main(String[] args) {
  //configure Chain of Responsibility
  Chain c1 = new NegativeProcessor();
  Chain c2 = new ZeroProcessor();
  Chain c3 = new PositiveProcessor();
  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));
 }
}



Example -2 

Email Processor

//Handler
This will be an interface which exposes primarily two methods.
One for specifying the next object and the other for processing the request.


public interface EmailHandler{

//reference to the next handler in the chain
public void setNext(EmailHandler handler);

//handle request
public void handleRequest(Email email);

}


// Business Email
//This is one of the chain of objects

public class BusinessMailHandler implements EmailHandler{
         private EmailHandler next;


         public void setNext(EmailHandler handler){
         next = handler;
        }


        public void handleRequest(Email email){
            if(!email.getFrom().endsWith("@businessaddress.com"){
               next.handleRequest(email);
            }else{
           //handle request
          (move to correct folder)
       }
     }
}


//This is one of the chain of objects
public class GMailHandler implements EmailHandler{
     private EmailHandler next;
   
     public void setNext(EmailHandler handler){
          next = handler;
     }

     public void handleRequest(Email email) {
      
         if(!email.getFrom().endsWith("@gmail.com"){
              next.handleRequest(email);
         }else{
         //handle request
        //(move to correct folder)
          }
      }
}


//This is the processor class which handles the objectsone of the chain of objects

public class EmailProcessor{
     //maintain a reference to the previous handler so we can add the
     //next one
     private EmailHandler prevHandler;

      public void addHandler(EmailHandler handler){
          if(prevHandler != null){
               prevHandler.setNext(handler);
          }
           prevHandler = handler;
     }
}

//email client
public class EmailClient{
             private EmailProcessor processor;
             //
             public EmailClient(){
                  createProcessor();
             }


            private void createProcessor(){
                  processor = new EmailProcessor();
                  processor.addHandler(new BusinessMailHandler());
                  processor.addHandler(new PersonalMailHandler());
            }


           public void addRule(EmailHandler handler){
                  processor.addHandler(handler);
           }


            public void emailReceived(Email email){
                  processor.handleRequest(email);
           }


           public static void main(String[] args){
                EmailClient client = new EmailClient();
           }


}

No comments: