Definition: A software entity such as classes, modules, and functions should be open to extensions and closed to modifications.
The origin of the problem: During the life cycle of the software, when the original code of the software needs to be modified due to changes, upgrades and maintenance, errors may be introduced into the old code, and it may also force us to refactor the entire function, and the original code needs to be retested.
Solution: When the software needs to change, try to achieve the change by extending the behavior of the software entity, rather than modifying existing code.
The principle of opening and closing is the most basic design principle in object-oriented design, which guides us how to establish a stable and flexible system. The principle of opening and closing may be the most vague definition of the six principles of design pattern. It only tells us to open up and close modifications, but how can we be open up and closed down and not tell us clearly. In the past, if someone told me, "You must abide by the principle of opening and closing when designing", I would feel that he didn't say anything, but it seemed that he said everything. Because the principle of opening and closing is really too empty.
After carefully thinking and reading many articles on design patterns, I finally got a little understanding of the principle of opening and closing. In fact, we follow the first five principles of design patterns, and the purpose of using 23 design patterns is to follow the opening and closing principles. In other words, as long as we abide by the first five principles, the software designed will naturally conform to the opening and closing principles. This opening and closing principle is more like the "average score" of the degree of compliance of the first five principles. If the previous five principles are well followed, the average score will naturally be higher, which means that the software design opening and closing principles are well followed; if the previous five principles are not adhered to, it means that the opening and closing principles are not adhered to.
In fact, the author believes that the principle of opening and closing is nothing more than to express the meaning: build a framework with abstraction and expand details with implementation. Because of the flexibility and wide adaptability of abstraction, as long as the abstraction is reasonable, the stability of the software architecture can be basically maintained. For the variable details in the software, we use the implementation class derived from abstract to extend. When the software needs to change, we only need to re-derive an implementation class according to the needs to extend. Of course, the premise is that our abstraction must be reasonable and we must be forward-looking and foresighted in the changes in demand.
In the definition of the opening and closing principle, a software entity may refer to a software module, a local structure composed of multiple classes, or an independent class.
Any software needs to face an important problem, that is, their needs will change over time. When the software system needs to face new needs, we should try our best to ensure that the system design framework is stable. If a software design complies with the principle of opening and closing, it can be very convenient to expand the system, and there is no need to modify existing code when expanding, so that the software system has better stability and continuity while having adaptability and flexibility. As the software scale becomes larger and larger, the software life becomes longer and the software maintenance costs become higher and higher, and designing software systems that meet the opening and closing principles is becoming increasingly important.
In order to meet the principle of opening and closing, it is necessary to abstractly design the system, and abstraction is the key to the principle of opening and closing. In programming languages such as Java and C#, a relatively stable abstraction layer can be defined for the system, and different implementation behaviors can be moved to the specific implementation layer to complete. In many object-oriented programming languages, mechanisms such as interfaces and abstract classes are provided, through which the abstraction layer of the system can be defined and then extended through concrete classes. If you need to modify the behavior of the system, there is no need to make any changes to the abstraction layer. You only need to add new concrete classes to implement new business functions, so as to expand the functions of the system without modifying existing codes, and meet the requirements of the opening and closing principle.
The CRM system developed by Sunny Software can display various types of charts, such as pie charts and bar charts. In order to support multiple chart display methods, the original design plan is shown in the figure below:
The following code snippet exists in the display() method of the ChartDisplay class:
...... if (type.equals("pie")) { PieChart chart = new PieChart(); chart.display(); } else if (type.equals("bar")) { BarChart chart = new BarChart(); chart.display(); } ...... In this code, if you need to add a new chart class, such as LineChart, you need to modify the source code of the display() method of the ChartDisplay class and add a new judgment logic, which violates the principle of opening and closing.
The system is now reconfigured to make it conform to the principle of opening and closing.
In this example, since each chart class is programmed in the display() method of the ChartDisplay class, adding a new chart class has to modify the source code. The system can be refactored in an abstract way so that when adding new chart classes, there is no need to modify the source code, which satisfies the principle of opening and closing. The specific methods are as follows:
(1) Add an abstract chart class AbstractChart, and use various concrete chart classes as their subclasses;
(2) The ChartDisplay class is programmed for abstract chart classes, and the client decides which specific chart to use.
The structure after reconstruction is shown in the figure below:
In Figure 2, we introduce the abstract chart class AbstractChart, and ChartDisplay is programmed for the abstract chart class, and the client sets the instantiated specific chart object through the setChart() method. In the display() method of ChartDisplay, the display() method of the chart object is called to display the chart. If you need to add a new chart, such as LineChart, you only need to use LineChart as a subclass of AbstractChart and inject a LineChart object into ChartDisplay on the client, without modifying the source code of the existing class library.
Note: Because configuration files in formats such as xml and properties are plain text files, they can be edited directly through VI editor or notepad without compilation, in software development, modification of configuration files is generally not considered to be a modification of the system source code. If a system only involves modifying the configuration file when it is extended, and the original Java code or C# code has not made any modifications, the system can be considered a system that complies with the principle of opening and closing.