Skip to main content

Practice Problems for Open/ Closed Principle

Open/Closed Principle (OCP)

Practice Problems

To master the Open/Closed Principle, it's essential to engage in practical exercises and projects. Here are some complete coding exercises, sample projects, quizzes, and multiple-choice questions (MCQs) to help reinforce your understanding.

Coding Exercises

  • Exercise 1: Refactor a Class to Adhere to OCP:

    Given:

public class Invoice {
public double calculateDiscount(Invoice invoice, String type) {
if (type.equals("Regular")) {
return invoice.getAmount() * 0.1;
} else if (type.equals("VIP")) {
return invoice.getAmount() * 0.2;
}
return 0;
}
}

Refactored:

public abstract class DiscountStrategy {
public abstract double calculateDiscount(Invoice invoice);
}

public class RegularDiscountStrategy extends DiscountStrategy {
@Override
public double calculateDiscount(Invoice invoice) {
return invoice.getAmount() * 0.1;
}
}

public class VipDiscountStrategy extends DiscountStrategy {
@Override
public double calculateDiscount(Invoice invoice) {
return invoice.getAmount() * 0.2;
}
}

public class Invoice {
private DiscountStrategy discountStrategy;

public Invoice(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}

public double calculateDiscount() {
return discountStrategy.calculateDiscount(this);
}
}
  • Exercise 2: Add New Functionality without Modifying Existing Code:

    Given:

public class NotificationService {
public void sendNotification(String type, String message) {
if (type.equals("Email")) {
sendEmail(message);
} else if (type.equals("SMS")) {
sendSMS(message);
}
}

private void sendEmail(String message) {
// Email sending logic
}

private void sendSMS(String message) {
// SMS sending logic
}
}

Refactored:

public interface Notification {
void send(String message);
}

public class EmailNotification implements Notification {
@Override
public void send(String message) {
// Email sending logic
}
}

public class SMSNotification implements Notification {
@Override
public void send(String message) {
// SMS sending logic
}
}

public class NotificationService {
private Notification notification;

public NotificationService(Notification notification) {
this.notification = notification;
}

public void sendNotification(String message) {
notification.send(message);
}
}
  • Exercise 3: Use OCP with a Strategy Pattern:

    Given:

public class PaymentService {
public void processPayment(String type, double amount) {
if (type.equals("CreditCard")) {
processCreditCardPayment(amount);
} else if (type.equals("PayPal")) {
processPayPalPayment(amount);
}
}

private void processCreditCardPayment(double amount) {
// Credit card payment logic
}

private void processPayPalPayment(double amount) {
// PayPal payment logic
}
}

Refactored:

public interface PaymentStrategy {
void pay(double amount);
}

public class CreditCardPaymentStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
// Credit card payment logic
}
}

public class PayPalPaymentStrategy implements PaymentStrategy {
@Override
public void pay(double amount) {
// PayPal payment logic
}
}

public class PaymentService {
private PaymentStrategy paymentStrategy;

public PaymentService(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}

public void processPayment(double amount) {
paymentStrategy.pay(amount);
}
}

Sample Projects

  • Project 1: Content Management System:
    • Description: Design a content management system (CMS) with separate classes for content creation, content editing, and content publishing. Each class should be open for extension but closed for modification.
    • Example:
public abstract class Content {
public abstract void create();
public abstract void edit();
public abstract void publish();
}

public class BlogPost extends Content {
@Override
public void create() {
// Blog post creation logic
}

@Override
public void edit() {
// Blog post editing logic
}

@Override
public void publish() {
// Blog post publishing logic
}
}

public class Article extends Content {
@Override
public void create() {
// Article creation logic
}

@Override
public void edit() {
// Article editing logic
}

@Override
public void publish() {
// Article publishing logic
}
}
  • Project 2: E-commerce System:
    • Description: Build an e-commerce system where different types of payment methods and shipping methods can be added without modifying the existing codebase.
    • Example:
public interface PaymentMethod {
void pay(double amount);
}

public class CreditCardPayment implements PaymentMethod {
@Override
public void pay(double amount) {
// Credit card payment logic
}
}

public class PayPalPayment implements PaymentMethod {
@Override
public void pay(double amount) {
// PayPal payment logic
}
}

public class PaymentService {
private PaymentMethod paymentMethod;

public PaymentService(PaymentMethod paymentMethod) {
this.paymentMethod = paymentMethod;
}

public void processPayment(double amount) {
paymentMethod.pay(amount);
}
}

Quizzes

  • Quiz 1: Identifying Violations of OCP:
    • Question: Given the following class, identify the violation of the Open/Closed Principle and suggest how to refactor it.
public class ReportGenerator {
public void generateReport(String type) {
if (type.equals("PDF")) {
generatePDFReport();
} else if (type.equals("Excel")) {
generateExcelReport();
}
}

private void generatePDFReport() {
// PDF report generation logic
}

private void generateExcelReport() {
// Excel report generation logic
}
}
  • Answer:
public interface Report {
void generate();
}

public class PDFReport implements Report {
@Override
public void generate() {
// PDF report generation logic
}
}

public class ExcelReport implements Report {
@Override
public void generate() {
// Excel report generation logic
}
}

public class ReportGenerator {
private Report report;

public ReportGenerator(Report report) {
this.report = report;
}

public void generateReport() {
report.generate();
}
}
  • Quiz 2: Benefits of OCP:
    • Question: What are the main benefits of adhering to the Open/Closed Principle? Provide examples.
    • Answer:
      • Maintainability: By ensuring that classes are open for extension but closed for modification, code becomes easier to maintain. New functionality can be added without altering existing code, reducing the risk of introducing bugs.
      • Scalability: Systems designed with OCP are more scalable because new features can be added independently of existing functionality.
      • Flexibility: Adhering to OCP allows for more flexible code. Different implementations of a functionality can be swapped in and out without modifying the core logic.
      • Examples:
        • Adding new payment methods to an e-commerce system without modifying the existing payment processing logic.
        • Implementing new report formats in a reporting system without changing the core report generation code.

Multiple-Choice Questions (MCQs)

  • MCQ 1: What does the Open/Closed Principle state?

    • A) Software entities should be open for modification but closed for extension
    • B) Software entities should be open for extension but closed for modification
    • C) Software entities should be closed for both modification and extension
    • D) Software entities should be open for both modification and extension

    Answer: B) Software entities should be open for extension but closed for modification

  • MCQ 2: Which of the following is a benefit of adhering to OCP?

    • A) Increased code complexity
    • B) Reduced code maintainability
    • C) Easier to add new functionality
    • D) Higher risk of introducing bugs

    Answer: C) Easier to add new functionality

  • MCQ 3: How can the Strategy Pattern help in adhering to OCP?

    • A) By allowing multiple algorithms to be defined and swapped without modifying the client code
    • B) By enforcing a single algorithm throughout the codebase
    • C) By making the code more difficult to extend
    • D) By combining multiple responsibilities into a single class

    Answer: A) By allowing multiple algorithms to be defined and swapped without modifying the client code