Open Closed Principle in Java with Examples
Last Updated :
02 Jan, 2023
In software development, the use of object-oriented design is crucial. It helps to write flexible, scalable, and reusable code. It is recommended that the developers follow SOLID principles when writing a code. One of the five SOLID principles is the open/closed principle. The principle states that software entities like class, modules, functions, etc.; should be able to extend a class behavior without modifying it. This principle separates the existing code from modified mode to provide better stability, maintainability and minimizes the changes in the code. In a nutshell, the developer must need to change only a specific part of the code (a class or a function) every time a requirement changes.
Using a statically typed language like Java, C#, etc. the open/closed principle is generally achieved by using inheritance and polymorphism. Let’s understand it with a few examples.
Implementation:
Program to calculate the volume in which let us consider the task of building an application that calculates the volumes of all the geometric objects.
- The Cuboid class stores dimensions of the cuboid
- Later on, the Application class calculates the total volume of the geometric objects–which are only cuboids currently.
- Run class helps to run the whole program.
Example 1:
Java
class Cuboid {
public double length;
public double breadth;
public double height;
}
class Application {
public double get_total_volume(Cuboid[] geo_objects)
{
double vol_sum = 0 ;
for (Cuboid geo_obj : geo_objects) {
vol_sum += geo_obj.length * geo_obj.breadth
* geo_obj.height;
}
return vol_sum;
}
}
public class GFG {
public static void main(String args[])
{
Cuboid cb1 = new Cuboid();
cb1.length = 5 ;
cb1.breadth = 10 ;
cb1.height = 15 ;
Cuboid cb2 = new Cuboid();
cb2.length = 2 ;
cb2.breadth = 4 ;
cb2.height = 6 ;
Cuboid cb3 = new Cuboid();
cb3.length = 3 ;
cb3.breadth = 12 ;
cb3.height = 15 ;
Cuboid[] c_arr = new Cuboid[ 3 ];
c_arr[ 0 ] = cb1;
c_arr[ 1 ] = cb2;
c_arr[ 2 ] = cb3;
Application app = new Application();
double vol = app.get_total_volume(c_arr);
System.out.println( "The total volume is " + vol);
}
}
|
Output
The total volume is 1338.0
Now, lets say the customer wants the application to calculate the volume of a sphere as well. In order to accommodate new type of geometric object, the application also needs to be changed.
Example 2:
Java
class Cuboid {
public double length;
public double breadth;
public double height;
}
class Sphere {
public double radius;
}
class Application {
public double get_total_volume(Cuboid[] c_geo_objects,
Sphere[] s_geo_objects)
{
double vol_sum = 0 ;
for (Cuboid geo_obj : c_geo_objects) {
vol_sum += geo_obj.length * geo_obj.breadth
* geo_obj.height;
}
for (Sphere geo_obj : s_geo_objects) {
vol_sum += ( 4 / 3 ) * Math.PI * geo_obj.radius
* geo_obj.radius * geo_obj.radius;
}
return vol_sum;
}
}
public class GFG {
public static void main(String args[])
{
Cuboid cb1 = new Cuboid();
cb1.length = 5 ;
cb1.breadth = 10 ;
cb1.height = 15 ;
Cuboid cb2 = new Cuboid();
cb2.length = 2 ;
cb2.breadth = 4 ;
cb2.height = 6 ;
Cuboid cb3 = new Cuboid();
cb3.length = 3 ;
cb3.breadth = 12 ;
cb3.height = 15 ;
Cuboid[] c_arr = new Cuboid[ 3 ];
c_arr[ 0 ] = cb1;
c_arr[ 1 ] = cb2;
c_arr[ 2 ] = cb3;
Sphere sp1 = new Sphere();
sp1.radius = 5 ;
Sphere sp2 = new Sphere();
sp2.radius = 2 ;
Sphere sp3 = new Sphere();
sp3.radius = 3 ;
Sphere[] s_arr = new Sphere[ 3 ];
s_arr[ 0 ] = sp1;
s_arr[ 1 ] = sp2;
s_arr[ 2 ] = sp3;
Application app = new Application();
double vol = app.get_total_volume(c_arr, s_arr);
System.out.println( "The total volume is " + vol);
}
}
|
Output
The total volume is 1840.6548245743668
Output Explanation:
As we can see the application class had to be changed to accommodate the sphere. Any changes in a code can lead to some unexpected errors in the future–so it is not advisable to change the well-tested code every time requirements change. Let’s try to apply the Open Close principle and see if we can add a sphere (a new type of object) without making any changes to the application class.
Solution:
- Create an abstract class that serves as a base class for all types of objects.
- All the geometric objects have a set of dimensions and a get_volume method (both of which are different for each type of object).
- For each type of object (a geometric object in this case) inherit the ‘Geo_object’ class, add the dimensions for that type of object and override the ‘get_volume‘ method.
- As it is apparent that by shifting the volume calculation from the ‘Application’ class to a different class, adding a new type of geometric object would not require changing the ‘Application’ class.
Example 3:
Java
import java.math.*;
abstract class Geo_objects {
public abstract double get_volume();
}
class Cuboid_2 extends Geo_objects {
public double length;
public double breadth;
public double height;
public double get_volume()
{
return length * breadth * height;
}
}
class Sphere_2 extends Geo_objects {
public double radius;
public double get_volume()
{
return ( 4 / 3 ) * Math.PI * radius * radius * radius;
}
}
class Application {
public double
get_total_volume(Geo_objects[] geo_objects)
{
double vol_sum = 0 ;
for (Geo_objects geo_obj : geo_objects) {
vol_sum += geo_obj.get_volume();
}
return vol_sum;
}
}
public class GFG {
public static void main(String args[])
{
Cuboid_2 cb1 = new Cuboid_2();
cb1.length = 5 ;
cb1.breadth = 10 ;
cb1.height = 15 ;
Cuboid_2 cb2 = new Cuboid_2();
cb2.length = 2 ;
cb2.breadth = 4 ;
cb2.height = 6 ;
Cuboid_2 cb3 = new Cuboid_2();
cb3.length = 3 ;
cb3.breadth = 12 ;
cb3.height = 15 ;
Sphere_2 sp1 = new Sphere_2();
sp1.radius = 5 ;
Sphere_2 sp2 = new Sphere_2();
sp2.radius = 2 ;
Sphere_2 sp3 = new Sphere_2();
sp3.radius = 3 ;
Geo_objects[] g_arr = new Geo_objects[ 6 ];
g_arr[ 0 ] = cb1;
g_arr[ 1 ] = cb2;
g_arr[ 2 ] = cb3;
g_arr[ 3 ] = sp1;
g_arr[ 4 ] = sp2;
g_arr[ 5 ] = sp3;
Application app = new Application();
double vol = app.get_total_volume(g_arr);
System.out.println( "The total volume is " + vol);
}
}
|
Output
The total volume is 1840.6548245743668
Output Explanation:
The Application class is closed for modification. Please note there may be other ways to achieve the Open Close principle–ours is just one of the possible approaches.
On taking an overview, we found that our first approach wasn’t open for extension and required modification in the code to accommodate new requirements (new geometric objects) . While the second approach was open for extension and adding new requirements can be done without modifying any existing code. The second approach helps to achieve robustness in the whole program.
Share your thoughts in the comments
Please Login to comment...