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.
Great introduction to Java. Looking forward to reading more posts.
ReplyDelete