Examples of Open/Closed Principle
Open/Closed Principle (OCP)
Examples
Bad Example: Violating OCP
Consider a simple example of a PaymentProcessor
class that handles different
types of payments.
- Java
- JavaScript
- Python
public class PaymentProcessor {
public void processPayment(String type) {
if (type.equals("CreditCard")) {
// Process credit card payment
} else if (type.equals("PayPal")) {
// Process PayPal payment
} else if (type.equals("Bitcoin")) {
// Process Bitcoin payment
}
}
}
class PaymentProcessor {
processPayment(type) {
if (type === 'CreditCard') {
// Process credit card payment
} else if (type === 'PayPal') {
// Process PayPal payment
} else if (type === 'Bitcoin') {
// Process Bitcoin payment
}
}
}
class PaymentProcessor:
def process_payment(self, type):
if type == 'CreditCard':
# Process credit card payment
elif type == 'PayPal':
# Process PayPal payment
elif type == 'Bitcoin':
# Process Bitcoin payment
In these examples, adding a new payment type requires modifying the
PaymentProcessor
class, which violates the Open/Closed Principle.
Good Example: Adhering to OCP
We can refactor the PaymentProcessor
class to adhere to OCP by using an
interface and implementing different payment types.
- Java
- JavaScript
- Python
public interface PaymentMethod {
void process();
}
public class CreditCardPayment implements PaymentMethod {
@Override
public void process() {
// Process credit card payment
}
}
public class PayPalPayment implements PaymentMethod {
@Override
public void process() {
// Process PayPal payment
}
}
public class BitcoinPayment implements PaymentMethod {
@Override
public void process() {
// Process Bitcoin payment
}
}
public class PaymentProcessor {
private PaymentMethod paymentMethod;
public PaymentProcessor(PaymentMethod paymentMethod) {
this.paymentMethod = paymentMethod;
}
public void processPayment() {
paymentMethod.process();
}
}
class PaymentMethod {
process() {
throw new Error('Method not implemented')
}
}
class CreditCardPayment extends PaymentMethod {
process() {
// Process credit card payment
}
}
class PayPalPayment extends PaymentMethod {
process() {
// Process PayPal payment
}
}
class BitcoinPayment extends PaymentMethod {
process() {
// Process Bitcoin payment
}
}
class PaymentProcessor {
constructor(paymentMethod) {
this.paymentMethod = paymentMethod
}
processPayment() {
this.paymentMethod.process()
}
}
from abc import ABC, abstractmethod
class PaymentMethod(ABC):
@abstractmethod
def process(self):
pass
class CreditCardPayment(PaymentMethod):
def process(self):
# Process credit card payment
class PayPalPayment(PaymentMethod):
def process(self):
# Process PayPal payment
class BitcoinPayment(PaymentMethod):
def process(self):
# Process Bitcoin payment
class PaymentProcessor:
def __init__(self, payment_method):
self.payment_method = payment_method
def process_payment(self):
self.payment_method.process()
In these refactored examples, adding a new payment type only requires creating a
new class that implements the PaymentMethod
interface. The PaymentProcessor
class remains unchanged, adhering to OCP.
Real-World Scenario
Consider an e-commerce platform that initially supports only credit card payments. As the business grows, it wants to add support for PayPal and Bitcoin payments.
- Initial Implementation: The original
PaymentProcessor
class handles only credit card payments. - Requirement Change: The business needs to add PayPal and Bitcoin payments without disrupting the existing payment processing.
- Solution: By refactoring the
PaymentProcessor
to use thePaymentMethod
interface, the platform can extend payment methods by adding new classes likePayPalPayment
andBitcoinPayment
without modifying the existingPaymentProcessor
class.
This approach ensures the system is scalable and maintainable, allowing new features to be added with minimal risk and effort, demonstrating the practical application of the Open/Closed Principle in a real-world scenario.