Open-Closed Principle
About 708 wordsAbout 2 min
2025-03-27
Definition
Software entities (classes, modules, functions) should be open for extension but closed for modification.
Open for extension means that when there are new requirements or changes, the existing code can be extended to adapt to new situations.
Closed for modification means that once the class is designed, it can complete its work independently without making any modifications to the existing code.
Open-Closed Principle is the most basic principle to judge whether object-oriented is correct.
Function
The Open-Closed Principle is the ultimate goal of object-oriented programming. It enables software entities to have certain adaptability and flexibility while having stability and continuity. Specifically, its functions are as follows:
- Impact on software testing. If the software complies with the open-closed principle, only the extended code needs to be tested during software testing, because the original test code can still run normally.
- It can improve the reusability of the code. The smaller the granularity, the greater the possibility of reuse. In object-oriented programming, programming based on atoms and abstractions can improve the reusability of the code.
- It can improve the maintainability of the software. Software that complies with the open-closed principle has high stability and strong continuity, making it easy to expand and maintain.
Implementation Method
The open-closed principle can be implemented through "abstract constraints, encapsulation changes", that is, a relatively stable abstract layer is defined for the software entity through an interface or an abstract class, and the same variable factors are encapsulated in the same specific implementation class.
- Abstract the unchanged part into an interface.
- The principle of minimum interface functionality. The smaller the interface, the stronger the reusability. The insufficient part can be implemented through a new interface.
- Calls are made between modules through abstract interfaces. Even if the implementation changes, there is no need to modify the caller's code.
Example
Now consider implementing a function: creating a drawing board that can draw various polygons.
Counter Example
enumShapeType{isCircle, isSquare};
typedef struct Shape {
enumShapeType type
} shape;
typedef struct Circle {
enumShapeType type;
double radius;
Point center;
} circle;
void drawCircle( circle* );
typedef struct Square {
enumShapeType type;
double side;
Point topleft;
} square;
void drawSquare( square* );
#include "Shape.h"
#include "Circle.h"
#include "Square.h"
void drawShapes( shape* list[], int n ) {
for( int i=0; i<n; i++ ) {
shape* s= list[i];
switch( s->type ) {
case isSquare:
drawSquare( (square*)s );
break;
case isCircle:
drawCircle( (circle*)s );
break;
}
}
}
We can see that in the above example, if we need to add a type of polygon:
- The
Shape
class is not extended, and theenumShapeType
enumeration type needs to be added. drawShapes
is not closed, and the code needs to be modified to add acase
.
Positive Example
#ifndef SHAPE_H
#define SHAPE_H
class Shape {
public:
virtual void draw() = 0; // pure virtual function
virtual ~Shape() {} // virtual destructor
};
#endif
#ifndef CIRCLE_H
#define CIRCLE_H
#include "Shape.h"
#include "Point.h" // Assume you have a Point type
class Circle : public Shape {
private:
double radius;
Point center;
public:
Circle(double r, Point c) : radius(r), center(c) {}
void draw() override {
// Code for drawing a circle
}
};
#endif
#ifndef SQUARE_H
#define SQUARE_H
#include "Shape.h"
#include "Point.h" // Assume you have a Point type
class Square : public Shape {
private:
double side;
Point topleft;
public:
Square(double s, Point tl) : side(s), topleft(tl) {}
void draw() override {
// Code for drawing a square
}
};
#endif
#include "Shape.h"
void drawShapes( shape* list[], int n ) {
for( int i=0; i<n; i++ ) {
list[i] -> draw();
}
}
In the above code, we introduced an abstract class and used polymorphism to draw graphics. In this way, if you need to add the function of drawing triangles in the future, you only need to add the following code and implement the draw()
method.
class Triangle : public Shape {
private:
Point p1, p2, p3;
public:
Triangle(Point a, Point b, Point c) : p1(a), p2(b), p3(c) {}
void draw() override {
// Code for drawing triangles
}
};
Contributors
Changelog
270fc
-feat(docs): add solid principles serieson
Copyright
Copyright Ownership:dingyuqi
License under:Attribution-NonCommercial-NoDerivatives 4.0 International (CC-BY-NC-ND-4.0)