The Open-Closed Principle (OCP) is one of the five SOLID principles of object-oriented design. It states that:
"Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification."
Explanation
- Open for extension: You should be able to add new functionality without changing the existing code.
- Closed for modification: You should not modify existing code when adding new features.
This principle helps write flexible, maintainable, and scalable code, reducing the risk of introducing bugs when modifying existing functionality.
Example of Violating the Open-Closed Principle
Here’s an example of a class that violates the Open-Closed Principle: We modify the DiscountCalculator
class every time a new customer type is added.
Bad Example (Violating OCP)
class DiscountCalculator {
public double calculateDiscount(String customerType, double amount) {
if (customerType.equals("Regular")) {
return amount * 0.1; // 10% discount for regular customers
} else if (customerType.equals("Premium")) {
return amount * 0.2; // 20% discount for premium customers
}
return 0;
}
}
Problems:
- If a new customer type (e.g., "VIP") needs to be added, we must modify this class.
- The
calculateDiscount
method has to be edited every time a new customer type is introduced, violating OCP. - More modifications mean a higher chance of breaking existing functionality.
Applying the Open-Closed Principle
To follow the OCP, we use polymorphism and abstraction. Instead of modifying an existing class, we create new classes that extend the functionality.
Good Example (Following OCP)
// Step 1: Define an interface for discount strategy
interface DiscountStrategy {
double applyDiscount(double amount);
}
// Step 2: Implement different discount strategies
class RegularCustomerDiscount implements DiscountStrategy {
@Override
public double applyDiscount(double amount) {
return amount * 0.1; // 10% discount
}
}
class PremiumCustomerDiscount implements DiscountStrategy {
@Override
public double applyDiscount(double amount) {
return amount * 0.2; // 20% discount
}
}
// Step 3: Use the strategy without modifying the existing class
class DiscountCalculator {
public double calculateDiscount(DiscountStrategy strategy, double amount) {
return strategy.applyDiscount(amount);
}
}
// Step 4: Usage
public class Main {
public static void main(String[] args) {
DiscountCalculator calculator = new DiscountCalculator();
DiscountStrategy regularDiscount = new RegularCustomerDiscount();
DiscountStrategy premiumDiscount = new PremiumCustomerDiscount();
double regularAmount = calculator.calculateDiscount(regularDiscount, 1000);
double premiumAmount = calculator.calculateDiscount(premiumDiscount, 1000);
System.out.println("Regular Customer Discount: " + regularAmount);
System.out.println("Premium Customer Discount: " + premiumAmount);
}
}
Advantages of Following OCP:
- No modifications to existing classes when adding a new discount type.
- Extensible design - You can add a new customer type (e.g., VIPCustomerDiscount
) by creating a new class implementing DiscountStrategy
.
- Better maintainability and readability.
- Follows the Single Responsibility Principle (SRP) by separating concerns.
Extending the System
Now, if a new type of discount needs to be added, you just create a new class:
class VIPCustomerDiscount implements DiscountStrategy {
@Override
public double applyDiscount(double amount) {
return amount * 0.3; // 30% discount for VIP customers
}
}
No need to modify the DiscountCalculator
class! 🎉
This is how the Open-Closed Principle helps write extensible and maintainable code in Java. 🚀
Thanks for reading! 🎉 I'd love to know what you think about the article. Did it resonate with you? 💭 Any suggestions for improvement? I’m always open to hearing your feedback so that I can improve my posts! 👇🚀. Happy coding! 💻✨
0 comments:
Post a Comment