开闭原则(Open-Closed Principle, OCP) 是面向对象设计中的重要原则之一,它的核心思想是:
- 对扩展开放(Open for extension):软件实体(类、模块、函数等)应该可以扩展,以满足新的需求。
- 对修改关闭(Closed for modification):在扩展功能时,不应该修改已有的代码,而是通过新增代码来实现变化。
通俗理解
想象你经营了一家餐厅,菜单已经固定,但你想增加新菜品。
- 如果你直接修改菜单(修改已有代码),可能会影响老顾客的习惯,甚至导致错误。
- 更好的做法是:新增一个菜品(扩展代码),而不是修改现有菜单。
如何遵循开闭原则
- 使用抽象(接口或抽象类):让具体实现继承或实现抽象,而不是修改原有代码。
- 使用多态:基于抽象定义行为,不直接依赖具体实现。
- 组合优于继承:通过组合不同对象来扩展功能,而不是修改现有代码。
违反开闭原则的例子
假设我们有一个形状类 Shape
,它支持计算面积:
class Shape {
String type;
}
class AreaCalculator {
public double calculateArea(Shape shape) {
if (shape.type.equals("circle")) {
return Math.PI * 5 * 5; // 假设半径是5
} else if (shape.type.equals("rectangle")) {
return 10 * 5; // 假设长10宽5
}
return 0;
}
}
问题:
- 如果要添加新的形状(比如三角形),我们必须修改
calculateArea()
方法,违反了开闭原则。
符合开闭原则的实现
我们可以使用抽象类来避免修改已有代码:
abstract class Shape {
abstract double getArea();
}
class Circle extends Shape {
double radius;
Circle(double radius) { this.radius = radius; }
double getArea() { return Math.PI * radius * radius; }
}
class Rectangle extends Shape {
double width, height;
Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
double getArea() { return width * height; }
}
class AreaCalculator {
public double calculateArea(Shape shape) {
return shape.getArea(); // 直接调用多态方法
}
}
好处:
- 不修改
AreaCalculator
的代码,而是扩展Shape
,符合开闭原则。 - 如果新增
Triangle
,只需创建新类,而不影响AreaCalculator
。
总结
开闭原则的核心是:扩展功能时,不要修改已有代码,而是新增代码。
它使代码更稳定、更易维护,符合面向对象编程的设计理念。