Definition: Software entities (classes, modules, functions, etc.) should be extensible but not modifyable. Open for expansion, closed for change. The key is abstraction, which clearly separates the general parts of a feature from the implementation details.
Here we are required to have abstract concepts when writing code. What is abstraction? Refers to the thinking process of abstracting concepts from entities. It is to extract common essential characteristics from numerous objects. In the process of writing code, where an abstract class is needed, you only need to grasp the essential function of this class, and don't always think about its specific function in this project.
Let’s continue to look at the open and closed principle. This principle requires that the shared part and the implementation part of a function be clearly separated. Because you cannot predict all the changes that will occur when you first build the architecture, then this class will not remain unchanged. As you implement it in each module, you will find that the abstract class is suitable for this function, but It is not suitable for another function. So do you want to go back and modify the abstract class? This cost is very high and requires re-thinking and adjusting specific details. It's better if the program hasn't been released yet. Once the program is released, going back to modify the abstract class will have a greater impact. Therefore, when starting to abstract, we must prevent this phenomenon from happening and follow the open and closed principle. Abstract classes and interfaces are standards. Once defined in a program, they cannot be easily modified. What should I do if the requirements change? You can extend this interface, rewrite methods, or add new methods after inheritance, but be sure not to modify it.
The following two examples are used to illustrate the open and closed principle.
1. Connect to the database as an example.
For example, the different types of database connections used in the program, Access and Oracle. The direct connection is as follows:
class ConnectAccess { public string ConnectString() { string dataPath = "数据库路径"; return string.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Persist Security Info=True;Jet OLEDB:Database Password={1}", dataPath, "密码"); } } class ConnectOracle { public string ConnectString() { return @"server=localhost;database=命名空间;uid=用户名;pwd=密码"; } }
Call
static void Main(string[] args) { //连接Access ConnectAccess connAccess = new ConnectAccess(); OleDbConnection accessConnection = new OleDbConnection(connAccessConnectString()); //连接Oracle ConnectOracle connOracle = new ConnectOracle(); OracleConnection oracleConnection = new OracleConnection(connOracleConnectString()); }
so you have to consider it every time Which parameters of OleDbConnection are used? Modify it below. Abstract an interface.
interface ConnectDataBase { string ConnectString(); } class ConnectAccess : ConnectDataBase { #region ConnectDataBase 成员 public string ConnectString() { string dataPath = "数据库路径"; return stringFormat("Provider=MicrosoftJetOLEDB0;Data Source={0};Persist Security Info=True;Jet OLEDB:Database Password={1}", dataPath, "密码"); } #endregion } class ConnectOracle : ConnectDataBase { #region ConnectDataBase 成员 public string ConnectString() { return @"server=localhost;database=命名空间;uid=用户名;pwd=密码"; } #endregion }
Call
static void Main(string[] args) { ConnectDataBase conn = null; //连接Access conn = new ConnectAccess(); OleDbConnection accessConnection = new OleDbConnection(connConnectString()); //连接Oracle conn = new ConnectOracle(); OracleConnection oracleConnection = new OracleConnection(connConnectString()); }
After the change, you only need to care about which class conn uses Instantiate and that's it. However, you may see that since Oracle connection requires OracleConnection, the advantages may not be easy to see.
2. Take the basic type as a method parameter as an example.
This is the reason why general design principles emphasize that method parameters should avoid basic types as much as possible. Compare the following two method definitions:
//定义1 bool Connect(string userName, string password, string wifiAddress, int port) { return false; }
//定义2 bool Connect(Account account) { return false; }
public class Account { public string UserName { get; set; } public string Password { get; set; } public string WifiAddress { get; set; } public int Port { get; set; } }
In comparison , Definition 2 has one more definition of Account class, and the Connect() method is obviously more stable. If the Connect() method wifiAddress changes, definition 1 must modify the interface of the method, and accordingly, all objects that call the Connect() method will be affected; while definition 2 only needs to modify the Account class, because the interface of the Connect() method remains remains unchanged, and the caller of the Connect() method does not need the wifiAddress. Such modification will not affect the caller at all, thereby reducing the impact of demand changes.
In short, the most important thing about the open and closed principle is abstraction, but it does not mean that once the abstract interface and class are determined, they must not be modified. However, when we are abstracting, we must think comprehensively and strive to avoid modification. Once the requirements change, we only need to make changes during implementation. Of course, the needs are ever-changing. Once the abstract part needs to be changed, as long as the principle is strictly followed, the impact will be much smaller. Of course, if it is modified, unit testing must be performed, and everything used must be tested correctly.
The above is the detailed content of Detailed explanation of the open and closed principle in Java. For more information, please follow other related articles on the PHP Chinese website!