Skip to main content

Design Pattern in Java

Why Design Pattern

In 1994, four authors Erich Gamma, Richard Helm, Ralph Johnson und John Vlissides published a book titled Design Patterns - Elements of Reusable Object-Oriented Software which initiated the concept of Design Pattern in Software development. The idea was to compile a list of common design patterns which can be used by programmers while designing the complex software. All the design patterns in this book are based on the two principles:
• Program to an interface, not an implementation.
• Favor object composition over inheritance.

Let's discuss these two principles in detail.

Program to an interface, not an implementation:
This principle means that when we create an object, we should create an object for the interface and not the implementation.

Example:
  • ArrayList myList = new ArrayList(); //Bad
  • List myList = new ArrayList(); //Good
  • List myList = new TreeList(); // Good
In this example, the first declaration is bad because if you plan to use tree list later. You need to change both the constructor and the variable type. On the contrary, if you plan to use the second or third declaration, then we only need to change the constructor in the declaration.

Favor object composition over inheritance:

The different classes can be related using two different ways - Composition or inheritance. If there is a choice between the two, try to use composition. Before we understand the importance of composition over inheritance, let's first discuss what is inheritance.

Inheritance:

Inheritance creates a "Is a" relationship between different classes. Let's take an example:
//Super Class
public class ClassC{

    public int methodC(){
    }
}

//Sub Class
public class ClassD extends ClassC {
    public void methodD() {
    }
}

//Test
public class Test{
    public static void main(String[] args) {
        ClassD obj = new ClassD();
        int output = obj.methodC();
    }
}

In this example, Class D extends Class C which means an object of Class D can access all the methods and variables of Class C. Let's say if we want to change the return type of methodC from int to String. It will break the code int the Class Test because it is expecting the return type as int. The composition can help us in this case. Let's see what a composition is and how can it be helpful.

Composition:

In composition, there exist a "Has a" relationship between two classes. It means one class contains an instance variable that holds the reference to another class. Let's take an example:

//Super Class
public class ClassC {
    public int methodC() {
    }
}

//Sub Class
public class ClassD {
    ClassC obj = new ClassC();

    public int methodCWrapper() {
        return obj.methodC();
    }

    public void methodD() {
    }
}

//Test
public class Test {
    public static void main(String[] args) {
        ClassD obj = new ClassD();
        int output = obj.methodCWrapper();
    }
}

In this example, Class D contains a constructor that takes an instance variable which is an object of the Super Class. Now, if we plan to change the return type of methodC from int to String we can do that without breaking the code in the Test class. We can make the changes in the methodCWrapper that will return the String to the method in the Test Class. In the change mentioned below, it can be seen that there was no change done in the Test class and code is still intact. That's why we should always prefer to use Composition as compared to inheritance for establishing a relationship between two or more classes.

//Super Class
public class ClassC {
    public String methodC() {
    }
}

//Sub Class
public class ClassD {
    ClassC obj = new ClassC();

// New change done here, so that no change is needed in
the client code in the test class.   
public int methodCWrapper() {
        return new Integer(obj.methodC()).toString();
    }

    public void methodD() {
    }
}

//Test
public class Test {
    public static void main(String[] args) {
        ClassD obj = new ClassD();
        int output = obj.methodCWrapper();
    }
}

In the next post, we will talk about the different types of design patterns.




Comments

  1. Great introduction to Java. Looking forward to reading more posts.

    ReplyDelete

Post a Comment

Popular posts from this blog

Builder Design Pattern

Introduction We will split our discussion into three sections - where to use this design pattern, how to use this design pattern and what is this design pattern. I will discuss what is builder design pattern at the end because the definition of any design pattern will not make sense until you know how and where to use it. In order to discuss where to use builder design pattern, we need to start with the problem statement. Problem Statement (Where to use builder design pattern): Create a class to store the following details of a customer in the database:      private String firstName; //required      private String lastName; //required      private String phone; //optional      private String shippingAddress; //optional      private String billingAddress; //optional public class User { private String firstName ; //required private String lastName ; //required private String phone ; //optional private String shippingAddress ; //optional

Types of Design Patterns

Types of Design Patterns Creational Pattern: This design pattern covers the different ways to create an object. We will discuss all of them in the later posts of this blog: Builder Abstract Factory Factory Method Object Pool Prototype Singleton Structural Pattern: Once an object is created, the next job is to create a relationship between the different objects and it can be done using a structural design pattern. The different types of structural design patterns that we will discuss in the future posts are: Adapter Aggregate Bridge Composite Decorator Extensibility Facade FlyWeight Marker Pipes and Filter Opaque Pointer Proxy Behavioral Pattern: In the last two patterns, we have created an object and established a relationship between different objects. Now, we need to figure out ways to communicate with the different objects. Behavioral design pattern helps us in channelizing the communication between the newly created objects. The different type