开闭原则
开闭原则
一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。
开放封闭原则指出软件实体(类、模块、函数等)应该是可扩展的,但不可修改的。
强调在添加新功能时应该通过扩展现有实体来实现,而不是修改现有实体的代码。 这样可以避免对已经稳定的代码进行修改,减少引入错误的风险。
当软件系统需要面对新的需求时,我们应该尽量保证系统的设计框架是稳定的。
如果一个软件设计符合开闭原则,那么可以非常方便地对系统进行扩展,而且在扩展时无须修改现有代码,使得软件系统在拥有适应性和灵活性的同时具备较好的稳定性和延续性。
要实现开闭原则,需要在程序设计开始时就对程序进行抽象化设计。
在抽象化模块设计完成之后,不允许修改接口或者抽象类的属性、方法;方法的参数类型、引用对象也必须是接口或者抽象类,尽量保证抽象层的稳定性; 在进行扩展时必须定义具体实现的方法。
举例说明
这里通过一个例子对开闭原则进行说明。例如:
定义一个 Shape 接口,它包含一个 calculateArea 方法。然后创建两个实现 Shape 接口的具体类 Rectangle 和 Circle。
每个类都实现了自己的 calculateArea 方法来计算不同形状的面积。
接下来,创建一个 AreaCalculator 类,它具有一个 calculateTotalArea 方法,用于计算给定形状数组的总面积。 这个方法接受一个 Shape 类型的数组作为参数,通过遍历数组并调用每个形状的 calculateArea 方法来计算总面积。
通过这种设计,遵循了开闭原则。当需要添加新的形状时,只需要创建一个新的类并实现 Shape 接口, 然后将新的形状对象传递给 calculateTotalArea 方法即可,而不需要修改现有的 AreaCalculator 类。
/**
* 开闭原则Demo
*/
interface Shape {
calculateArea: () => number
}
class Rectangle implements Shape {
private readonly width: number
private readonly height: number
constructor(width: number, height: number) {
this.width = width
this.height = height
}
calculateArea(): number {
return this.width * this.height
}
}
class Circle implements Shape {
private readonly radius: number
constructor(radius: number) {
this.radius = radius
}
calculateArea(): number {
return Math.PI * this.radius * this.radius
}
}
class AreaCalculator {
calculateTotalArea(shapes: Shape[]): number {
let totalArea = 0
for (const shape of shapes) {
totalArea += shape.calculateArea()
}
return totalArea
}
}
// 使用示例
const rectangle = new Rectangle(5, 10)
const circle = new Circle(7)
const areaCalculator = new AreaCalculator()
const totalArea = areaCalculator.calculateTotalArea([rectangle, circle])
console.log('Total Area:', totalArea)这样,通过扩展而不是修改现有代码来满足新需求,遵循了开闭原则。这样的设计使得系统更加灵活、可扩展,并且改动不会对现有功能产生不必要的影响。
开闭原则的实现由里氏替换原则和依赖倒置原则来完成。
更新日志
24657-于c0f2d-于6b33b-于e6a79-于
