The Open/Closed Principle (OCP) states that a software module (class, function, or component) should be open for extension but closed for modification. This means that you should be able to add new functionality to a module without changing its existing code. OCP is one of the SOLID principles in object-oriented programming.
Why Follow OCP?
- Avoid Breaking Existing Code: Reducing the risk of introducing bugs in tested and working code.
- Encourage Extensibility: Allows adding new features with minimal disruption.
- Improves Maintainability: Modular, extendable code is easier to maintain.
Real-Life Examples
1. Payment System
Imagine an e-commerce application that needs to process different payment methods (e.g., Credit Card, PayPal, Google Pay).
Violation of OCP:
public class PaymentProcessor {
public void processPayment(String paymentType) {
if (paymentType.equals("CreditCard")) {
System.out.println("Processing Credit Card Payment");
} else if (paymentType.equals("PayPal")) {
System.out.println("Processing PayPal Payment");
} else if (paymentType.equals("GooglePay")) {
System.out.println("Processing Google Pay Payment");
}
}
}
Issues:
- Every time a new payment method is added, the
processPayment
method must be modified. - This violates OCP because the class isn’t closed for modification.
Applying OCP:
Use an abstract class or interface to define a common contract for payment methods, allowing new payment methods to be added without modifying existing code.
java// Define a common interface public interface PaymentMethod { void processPayment(); } // Implement specific payment methods public class CreditCardPayment implements PaymentMethod { public void processPayment() { System.out.println("Processing Credit Card Payment"); } } public class PayPalPayment implements PaymentMethod { public void processPayment() { System.out.println("Processing PayPal Payment"); } } public class GooglePayPayment implements PaymentMethod { public void processPayment() { System.out.println("Processing Google Pay Payment"); } } // Payment processor uses abstraction public class PaymentProcessor { public void processPayment(PaymentMethod paymentMethod) { paymentMethod.processPayment(); } }
Adding a new payment method: To add a new payment method (e.g., Apple Pay), simply create a new class implementing the PaymentMethod
interface:
javapublic class ApplePayPayment implements PaymentMethod { public void processPayment() { System.out.println("Processing Apple Pay Payment"); } }
Let’s see another example.
Imagine a notification system that supports email and SMS notifications.
Violation of OCP:
javapublic class NotificationService { public void sendNotification(String type, String message) { if (type.equals("Email")) { System.out.println("Sending Email: " + message); } else if (type.equals("SMS")) { System.out.println("Sending SMS: " + message); } } }
Issues:
- Adding a new notification type (e.g., Push Notifications) requires modifying the
sendNotification
method. - This violates OCP.
Let’s give a try and fix it.