DEV Community

Fabrizio Bagalà
Fabrizio Bagalà

Posted on • Edited on

Open/Closed Principle

The Open/Closed Principle (OCP) states that:

Software entities should be open for extension but closed for modification.

This means that a class should allow for the addition of new functionalities without changing the existing code, while the behavior of existing classes should not be altered.

Violation of the principle

Imagine having a class that calculates the area of different geometric shapes:

public class AreaCalculator
{
    public double CalculateArea(object[] shapes)
    {
        var area = 0d;
        foreach (var shape in shapes)
        {
            if (shape is Rectangle)
            {
                var rectangle = (Rectangle)shape;
                area += rectangle.Width * rectangle.Height;
            }
            else if (shape is Circle)
            {
                var circle = (Circle)shape;
                area += Math.PI * Math.Pow(circle.Radius, 2);
            }
        }
        return area;
    }
}
Enter fullscreen mode Exit fullscreen mode

This implementation violates the OCP because each time we add a new geometric shape, we have to modify the CalculateArea method by adding a new conditional if block.

Application of the principle

To comply with the OCP, we can use inheritance and polymorphism by introducing an IShape interface with a CalculateArea method and ensuring that the classes of various shapes implement this interface:

public interface IShape
{
    double CalculateArea();
}

public class Rectangle : IShape
{
    public double Width { get; set; }
    public double Height { get; set; }

    public double CalculateArea()
    {
        return Width * Height;
    }
}

public class Circle : IShape
{
    public double Radius { get; set; }

    public double CalculateArea()
    {
        return Math.PI * Math.Pow(Radius, 2);
    }
}
Enter fullscreen mode Exit fullscreen mode

Now we can rewrite the AreaCalculator class to use polymorphism to calculate the area of shapes without having to modify the class each time a new geometric shape is added:

public class AreaCalculator
{
    public double CalculateArea(IShape[] shapes)
    {
        var area = 0d;
        foreach (var shape in shapes)
        {
            area += shape.CalculateArea();
        }
        return area;
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this article, we have explored the Open/Closed Principle, which guides us in creating classes and modules that are resistant to direct modifications but amenable to extensions. This principle emphasizes the use of abstractions and inheritance to add functionality to classes without altering their original implementation. The result is code that is easier to maintain and more extensible, reducing the impact of changes on pre-existing implementations.

References

Top comments (0)