Funding for 'IT Lab' Project, Phase 1: Progress of sticker sales. Purchase a sticker to help us reach our target.Updated: 2010-02-28 11:53
10.7%
Introduction to design patterns

 


by M.A.C.Sandarenu



During my previous set of articles I discussed some important practices and techniques which can be used to improve the quality of the software we write. From this month onwards I’m planning to write few articles on “Design Patterns”, which is again, can help us to write more efficient code.
Design patterns are set of solutions which can be used to solve problems we commonly encounter, when we write programs. Most of the problems we have to solve in our programs are already being solved by someone else. Here I’m not talking about the business problems intended to solve by our program; rather I’m talking about small problems we come across when we decompose that large problem in to series of small problems.  Design patterns are solutions for such problems.
Design patterns are not a new thing to the software industry; rather developers had used them for long time. They were first organized in to a book known as “Design Patterns – Elements of Reusable Software Patterns” by Gamma, Helm, Johnson and Vlissides more commonly known as “Gang of Four (GoF)”.
Patterns are not only used in general software development; rather they are also used in various other areas like UI development, concurrent application development, etc... In general software engineering design patters are categorized to three types; Creational Patterns, Structural Patterns and Behavioral Patterns.

Creational Patterns

These are group of patterns which talks about the class initiation.

  • Abstract Factory - Creates an instance of several families of classes
  • Builder - Separates object construction from its representation
  • Factory Method - Creates an instance of several derived classes
  • Object Pool - Avoid expensive acquisition and release of resources by recycling objects that are no longer in use
  • Prototype - A fully initialized instance to be copied or cloned
  • Singleton - A class of which only a single instance can exist

Structural Patterns

These are collection of patterns which explains about Class and Object composition.

  • Adapter - Match interfaces of different classes
  • Bridge - Separates an object’s interface from its implementation
  • Composite - A tree structure of simple and composite objects
  • Decorator - Add responsibilities to objects dynamically
  • Façade -  A single class that represents an entire subsystem
  • Flyweight - A fine-grained instance used for efficient sharing
  • Private Class Data - Restricts accessor/mutator access
  • Proxy - An object representing another object

Behavioral Pattern

These patterns are about the communication between objects.

  • Chain of responsibility - A way of passing a request between a chain of objects
  • Command - Encapsulate a command request as an object
  • Interpreter - A way to include language elements in a program
  • Iterator - Sequentially access the elements of a collection
  • Mediator - Defines simplified communication between classes
  • Memento - Capture and restore an object's internal state
  • Null Object - Designed to act as a default value of an object
  • Observer - A way of notifying change to a number of classes
  • State - Alter an object's behavior when its state changes
  • Strategy - Encapsulates an algorithm inside a class
  • Template method - Defer the exact steps of an algorithm to a subclass
  • Visitor - Defines a new operation to a class without change

Each design pattern comes with an Intent, which describes the situation where that particular design pattern is to be used. It is really important to know those intentions of the design pattern if we are to get the maximum productivity out of the design patterns. It is because when we come across some software problem we should be able to map our requirement with the intentions of different design patterns and select the most suited one. Even though it sounds like simple actually it is the most difficult part. 

Advantages

Design patterns are proven solutions for software engineering problems. They allow us to use expert’s knowledge on particular area of software development.
Design patterns are developed in highly cohesive manner with less coupling.  This allows us to separate the concerns easily and make it easy to understand software.
Use of design patterns make to communication between developers easy. Since these are widely known patterns, when you talks about that you have used some pattern in your programs other will quickly know what it is, you don’t have to explain much.

Disadvantages

Even though design patterns are a way of code reuse, they are not a direct way of reuse. You’ll have to map the design pattern to your requirement and may have to do some customizations as well.
Sometimes design patterns can add unwanted complexity to your program, since they are designed to be general solutions.
So now we have some idea about design patterns, it is the time to learn simple design pattern. We’ll start with “Chain of Responsibility Pattern”.

Chain of Responsibility Pattern

Chain of Responsibility Pattern describes a way of processing requests, when there are many processing elements without hardwiring the relationships, precedence or request to processing element mapping.


cor1.jpg

Intent

  • Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.
  • Launch-and-leave requests with a single processing pipeline that contains many possible handlers.
  • An object-oriented linked list with recursive traversal.

In this pattern our intention is to separate the coupling between request and its processing elements. Number and type of processing elements are not known a priori. They can be configured dynamically. Here instead of client maintaining references to possible processing elements; client keeps a single reference to the head of the processing element chain and each processing element maintains a reference to its successor in the chain.

cor-class-dig.gif


Here we have to place a mechanism to handle request which can go unhandled by any of the processing elements in the chain.

Example

I have done a simple application which can be used to perform various mathematical operations on two numbers. Processing of mathematical operations has being done as a chain. Check out the sample codes given below.

cor-sample.png

public interface Handler {

  double process(Request request);

  void addNextHandler(Handler nextDecoder);

  Handler getNextHandler();
}

public abstract class AbstractHandler implements Handler {
private Handler nextHandler;

  @Override
public void addNextHandler(Handler nextHandler) {
if (this.nextHandler == null) {
this.nextHandler = nextHandler;
} else {
this.nextHandler.addNextHandler(nextHandler);
}
}

  @Override
public Handler getNextHandler() {
return this.nextHandler;
}

  protected double passToNextHandler(Request request) {
Handler nextHandler = getNextHandler();
if (nextHandler != null) {
return nextHandler.process(request);
} else {
throw new RuntimeException("No handler found to process given request[" + request + "]");
}
}
}

public class AddHandler extends AbstractHandler {

  @Override
public double process(Request request) {
if (request.getOperation() == Operation.ADD) {
return request.getNum1() + request.getNum2();
} else {
return passToNextHandler(request);
}
}
}

public class DivideHandler extends AbstractHandler {

  @Override
public double process(Request request) {
if (request.getOperation() == Operation.DIVIDE) {
return request.getNum1() / request.getNum2();
} else {
return passToNextHandler(request);
}
}
}

public class Request {
public enum Operation {
ADD, SUBSTRACT, MULTIPLY, DIVIDE;
}

  private double num1;
private double num2;
private Operation operation;

  public Request(double num1, double num2, Operation operation) {
super();
this.num1 = num1;
this.num2 = num2;
this.operation = operation;
}
public double getNum1() {
return num1;
}
public double getNum2() {
return num2;
}
public Operation getOperation() {
return operation;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Request [num1=").append(num1).append(", num2=").append(num2).append(", operation=")
.append(operation).append("]");
return builder.toString();
}
}

public class Client {

  private static Handler handlerChain = new AddHandler();
static {
handlerChain.addNextHandler(new DivideHandler());
}

  public static double process(Request request) {

    return handlerChain.process(request);
}

  public static void main(String[] args) {
System.out.println("1 + 2: " + Client.process(new Request(1, 2, Operation.ADD)));
System.out.println("1 / 2: " + Client.process(new Request(1, 2, Operation.DIVIDE)));
System.out.println("1 * 2: " + Client.process(new Request(1, 2, Operation.MULTIPLY)));
}
}
This is really simple example just to show how Chain of Responsibility pattern cam be implemented. Hope you all get some idea about design patterns. Lets meet next month with another Design Pattern.

Post new comment

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options