Open/Closed Principle in Java

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

1. Overview

In this tutorial, we'll discuss the Open/Closed Principle (OCP) as one of the SOLID principles of object-oriented programming.

Overall, we'll go into detail on what this principle is and how to implement it when designing our software.

2. Open/Closed Principle

As the name suggests, this principle states that software entities should be open for extension, but closed for modification. As a result, when the business requirements change then the entity can be extended, but not modified.

For the illustration below, we'll focus on how interfaces are one way to follow OCP.

2.1. Non-Compliant

Let's consider we're building a calculator app that might have several operations, such as addition and subtraction.

First of all, we'll define a top-level interface – CalculatorOperation:

public interface CalculatorOperation {}

Let's define an Addition class, which would add two numbers and implement the CalculatorOperation:

Although this may seem fine, it's not a good example of the OCP. When a new requirement of adding multiplication or divide functionality comes in, we've no way besides changing the calculate method of the Calculator class.

Hence, we can say this code is not OCP compliant.

2.2. OCP Compliant

As we've seen our calculator app is not yet OCP compliant. The code in the calculate method will change with every incoming new operation support request. So, we need to extract this code and put it in an abstraction layer.

One solution is to delegate each operation into their respective class:

public interface CalculatorOperation {
void perform();
}

As a result, the Addition class could implement the logic of adding two numbers:

That way the class is closed for modification but open for an extension.

3. Conclusion

In this tutorial, we've learned what is OCP by definition, then elaborated on that definition. We then saw an example of a simple calculator application that was flawed in its design. Lastly, we made the design good by making it adhere to the OCP.

Hi Rix,
There’s nothing special in calling the calculate() method. Once you have the Calculator object instantiated, you can pass any implementation of the CalculatorOperation interface to the calculate() method.
Anyway, please check out our examples in the GitHub repository.
Cheers