To implement the Open/Closed Principle, you can use various techniques such as abstract classes, interfaces, and inheritance. Here are a few examples to illustrate how you can apply OCP in C#.
Example 1: Using Inheritance and Polymorphism
Consider a scenario where we have a base Shape class and several derived classes representing specific shapes.
public class Shape
{
public string Type { get; set; }
}
public class AreaCalculator
{
public double CalculateArea(Shape shape)
{
if (shape.Type == "Circle")
{
Circle circle = (Circle)shape;
return Math.PI * circle.Radius * circle.Radius;
}
else if (shape.Type == "Rectangle")
{
Rectangle rectangle = (Rectangle)shape;
return rectangle.Width * rectangle.Height;
}
// More shape types...
throw new ArgumentException("Unknown shape type");
}
}
public class Circle : Shape
{
public double Radius { get; set; }
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
}
In this design, the CalculateArea method in the AreaCalculator class needs to be modified every time a new shape is added, which violates the Open/Closed Principle.
public abstract class Shape
{
public abstract double CalculateArea();
}
public class Circle : Shape
{
public double Radius { get; set; }
public Circle(double radius)
{
Radius = radius;
}
public override double CalculateArea()
{
return Math.PI * Radius * Radius;
}
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
public override double CalculateArea()
{
return Width * Height;
}
}
public class AreaCalculator
{
public double CalculateArea(Shape shape)
{
return shape.CalculateArea();
}
}
In this refactored design, the Shape class is an abstract base class with a CalculateArea method that each derived class overrides. The AreaCalculator class no longer needs to be modified when a new shape is added, adhering to the Open/Closed Principle.