Friday 16 October 2015

Open-closed principle

Open-closed principle states that software entities such as classes, methods should be open for extension and closed for modification. That is we can extend the behavior of software entity, without touching the source code of the entity.

For example, there is a class ‘ConnectionFactory’, it provides number of methods to connect to databases like MySQL, MongoDB, Elasticsearch etc., Assume there are number of classes using this ConnectionFactory. Even if you change single line in ConnectionFactory class, you need to retest all the modules that are using ConnectionFactory class. If you design your code like this, you will end up in testing all the dependent modules often.

Open-closed principle solved this problem in straightforward way.

Rule 1: Design a module such that, it never change.

Rule 2: When requirements change, extend (Inheritance) the behavior of an entity by adding new code.

Modules that follow above two rules are open for extension and closed for modification.

How can I achieve open-closed principle?
Using abstraction and inheritance.

For example, I am developing a drawing board application. My initial requirement is, user can able to draw a circle and triangle. I am going to design using open-closed principle.
public interface Shape {
 void draw();
}

public class Circle implements Shape{

 @Override
 public void draw() {
  System.out.println("Drawn Circle");
 }

}

public class Triangle implements Shape{

 @Override
 public void draw() {
  System.out.println("Drawn Triangle");
 }

}

import java.util.List;

public class DrawUtil {
 public static void drawShapes(List<Shape> shapes){
  shapes.stream().forEach(Shape::draw);
 }
}

import java.util.*;

public class Main {
 public static void main(String args[]){
  List<Shape> shapes = new ArrayList<> ();
  
  shapes.add(new Circle());
  shapes.add(new Triangle());
  shapes.add(new Triangle());
  
  DrawUtil.drawShapes(shapes);
 }
}

Run Main.java, you will get following output.

Drawn Circle
Drawn Triangle
Drawn Triangle

Now user wants to draw squares also. Since we followed open-closed principle, we can add this functionality without touching existing modules. Define a class Square that implements Shape class, that’s it you are done.
public class Square implements Shape {

 @Override
 public void draw() {
  System.out.println("Drawn Square");
 }

}

import java.util.*;

public class Main {
 public static void main(String args[]){
  List<Shape> shapes = new ArrayList<> ();
  
  shapes.add(new Circle());
  shapes.add(new Triangle());
  shapes.add(new Triangle());
  shapes.add(new Square());
  
  DrawUtil.drawShapes(shapes);
 }
}

Output
Drawn Circle
Drawn Triangle
Drawn Triangle
Drawn Square

References
https://en.wikipedia.org/wiki/Open/closed_principle


No comments:

Post a Comment