Open Closed Principle in Java with Examples

Last Updated : 17 Apr, 2026

The Open Closed Principle (OCP) is one of the five SOLID principles of object-oriented design. It states that software entities (classes, modules, functions) should be open for extension but closed for modification. This means you should be able to add new functionality without changing existing, tested code.

  • Reduces the risk of introducing bugs in existing code
  • Makes applications easier to maintain and scale
  • Encourages clean, flexible, and reusable design

Implementation

Let us consider an application that calculates the total volume of geometric objects. Initially, the application supports only cuboids.

Example 1: Initial Implementation (Only Cuboids)

Design Overview

  • Cuboid class stores dimensions of a cuboid
  • Application class calculates total volume
  • Main class executes the program
Java
// Class representing a Cuboid
// Stores dimensions: length, breadth, and height
class Cuboid {
    public double length;
    public double breadth;
    public double height;
}

// Application class to calculate total volume
class Application {

    // Calculates total volume of all cuboids
    public double getTotalVolume(Cuboid[] objects) {
        double volumeSum = 0;

        // Iterate through each cuboid and calculate volume
        for (Cuboid obj : objects) {
            volumeSum += obj.length * obj.breadth * obj.height;
        }
        return volumeSum;
    }
}

// Main class to run the program
public class Main {
    public static void main(String[] args) {

        // Creating first cuboid and setting dimensions
        Cuboid c1 = new Cuboid();
        c1.length = 5;
        c1.breadth = 10;
        c1.height = 15;

        // Creating second cuboid and setting dimensions
        Cuboid c2 = new Cuboid();
        c2.length = 2;
        c2.breadth = 4;
        c2.height = 6;

        // Storing cuboids in an array
        Cuboid[] cuboids = { c1, c2 };

        // Calculating and printing total volume
        Application app = new Application();
        System.out.println("Total Volume: " + app.getTotalVolume(cuboids));
    }
}

Output
Total Volume: 798.0

Problem with This Approach

Now suppose the customer wants to add support for spheres.To do this, the Application class must be modified, which:

  • Violates the Open Closed Principle
  • Increases risk of future bugs
  • Makes the code harder to maintain

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: Violating Open Closed Principle

Here, the Application class is modified to support both cuboids and spheres.

Java
// Class representing a Sphere
class Sphere {
    public double radius;
}

// Modified Application class (violates OCP)
class Application {

    // Calculates volume for both cuboids and spheres
    // Needs modification whenever a new shape is added
    public double getTotalVolume(Cuboid[] cuboids, Sphere[] spheres) {
        double volumeSum = 0;

        // Calculating volume of cuboids
        for (Cuboid c : cuboids) {
            volumeSum += c.length * c.breadth * c.height;
        }

        // Calculating volume of spheres
        for (Sphere s : spheres) {
            volumeSum += (4.0 / 3) * Math.PI * s.radius * s.radius * s.radius;
        }

        return volumeSum;
    }
}

Issue: Every new geometric shape requires modifying the Application class, which clearly breaks OCP.

Solution: Applying Open Closed Principle

To follow OCP:

  • Move volume calculation logic to individual objects
  • Use abstraction and polymorphism
  • Keep the Application class unchanged

Example 3: OCP-Compliant Design

Step 1: Create an Abstract Base Class

Java
abstract class GeoObject {
    public abstract double getVolume();
}

Step 2: Extend Base Class for Cuboid

Java
class Cuboid extends GeoObject {
    public double length;
    public double breadth;
    public double height;

    @Override
    public double getVolume() {
        return length * breadth * height;
    }
}

Step 3: Extend Base Class for Sphere

Java
class Sphere extends GeoObject {
    public double radius;

    @Override
    public double getVolume() {
        return (4.0 / 3) * Math.PI * radius * radius * radius;
    }
}

Step 4: Keep Application Class Closed for Modification

Java
class Application {

    public double getTotalVolume(GeoObject[] objects) {
        double volumeSum = 0;

        for (GeoObject obj : objects) {
            volumeSum += obj.getVolume();
        }
        return volumeSum;
    }
}

Step 5: Main Class

Java
public class Main {
    public static void main(String[] args) {

        GeoObject[] objects = new GeoObject[] {
            new Cuboid(){{
                length = 5; breadth = 10; height = 15;
            }},
            new Sphere(){{
                radius = 5;
            }}
        };

        Application app = new Application();
        System.out.println("Total Volume: " + app.getTotalVolume(objects));
    }
}

Output

Total Volume: 1840.6548245743668

Comment