Solid Software Design: Applying the Open/Closed Principle (OCP) in Java


Definition
The Open/Closed Principle is one of the SOLID principles in software design. It states that a component should be open for extension but closed for modification. This means that we can add new functionalities without altering the existing code, improving the maintainability and scalability of the system.
Example in Java
Below is a Java example implementing this principle using a Discount interface and different discount strategies:
interface Discount {
double applyDiscount(double price);
}
class FixedDiscount implements Discount {
@Override
public double applyDiscount(double price) {
return price - 10;
}
}
class PercentageDiscount implements Discount {
@Override
public double applyDiscount(double price) {
return price * 0.9;
}
}
class Store {
public double calculateFinalPrice(double price, Discount discount) {
return discount.applyDiscount(price);
}
}
// Usage
public class Main {
public static void main(String[] args) {
Store store = new Store();
double price = 100;
System.out.println("Price with fixed discount: " + store.calculateFinalPrice(price, new FixedDiscount()));
System.out.println("Price with percentage discount: " + store.calculateFinalPrice(price, new PercentageDiscount()));
}
}
Explanation
In this design:
The Discount interface defines a contract for different discount types.
FixedDiscount and PercentageDiscount implement different discount strategies.
The Store class uses the Discount interface to calculate the final price, allowing new discount types to be added without modifying its code.
In the Main class, these strategies are demonstrated without affecting the existing structure.
This approach adheres to the Open/Closed Principle because if a new discount type is required in the future, we can simply create a new class implementing Discount without altering existing classes.
Automation with GitHub Actions
To ensure that the project builds and runs correctly on every code change, a Continuous Integration (CI) workflow was implemented using GitHub Actions. This allows the Java code to be compiled and executed automatically upon every push to the main
branch.
Here is the workflow configuration file (.github/workflows/java.yml
):
name: Java CI
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Compile code
run: javac src/*.java
- name: Run Main class
run: java -cp src Main
โ This pipeline performs the following steps:
Checks out the code from the repository.
Installs Java 17 using the Temurin distribution.
Compiles all
.java
files in thesrc
folder.Executes the
Main
class to validate the logic.
The CI automation ensures consistent behavior across environments, simplifies collaboration, and quickly detects errors after each push.
๐ฅ Watch code explanation on YouTube: https://www.youtube.com/watch?v=JNSkuRmwJ3o
The full source code and workflow can be explored here:
๐ GitHub Repository โ OCP Example in Java
Comparison with SRP and DIP
Principle | Definition | Key Advantage |
Single Responsibility Principle (SRP) | A class should have only one reason to change. | Simplifies debugging and maintenance by keeping each class focused on a single task. |
Open/Closed Principle (OCP) | A component should be open for extension but closed for modification. | Enhances flexibility by allowing new features to be added without altering existing code. |
Dependency Inversion Principle (DIP) | High-level modules should not depend on low-level modules; both should depend on abstractions. | Improves modularity and testability by reducing dependencies on concrete implementations. |
These principles together help in designing flexible, maintainable, and scalable software systems.
Conclusion
The Open/Closed Principle is essential for building scalable and maintainable applications. By ensuring that components are open for extension but closed for modification, we can introduce new functionalities without altering existing code, reducing the risk of introducing bugs and making the system more adaptable to future changes. When combined with other SOLID principles like SRP and DIP, OCP contributes to a more modular and robust software design, ultimately improving development efficiency and software quality.
Subscribe to my newsletter
Read articles from JAIME ELIAS FLORES QUISPE directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
