“This is the fourth day of my participation in the August More Text Challenge. For details, see: August More Text Challenge.”
preface
At the top end of the interview, often encounter some questions about design patterns, each time the answer is not ideal. Coincides with the more challenging activities in August, I am prepared to spend a month to get a good understanding of design patterns, so as to increase my confidence for the interview.
Before learning about design patterns, it is important to recognize that design patterns are programming ideas that can be applied to any programming language. Secondly, we should learn from the principles of design patterns, so this paper will introduce in detail one of the principles of design patterns, the Richter substitution principle.
The official definition of
If for every object O1 of type T1, there is an object O2 of type T2, such that all programs P defined in T1 behave the same when all objects O1 is replaced with O2, then type T2 is a subtype of type T1.
Your own understanding
The official definition is confusing. In the vernal language, it says: in a program, replace the parent class with its child class, and the program will still work.
The Richter substitution principle is the premise of the open-close principle. Why is that? In the open-close principle, the parent class remains closed, and the parent class is extended in the way that the subclass continues the parent class to achieve openness. The parent class remains closed so that the parent class can be reused. However, in the actual development process, in the process of inheriting the parent class to create a subclass, often make a mistake, in the subclass to modify the methods and attributes of the parent class, which leads to the parent class is not closed, if the parent class is reused, it is likely to appear unexpected bugs.
Here’s an example:
class A { constructor() { } storageData() { api.getTaskList1() .then(res =>{ localStorage.setItem(taskData", JSON.stringify(res.data) ); }) } } class B extends A { constructor() { super(); } storageData() { api.getTaskList2() .then(res =>{ localStorage.setItem("taskData", JSON.stringify(res.data)); }}})Copy the code
Const A = new A(); const A = new A(); const A = new A(); a.storageData(); Ask the getTaskList1 interface to cache the data it gets into the taskData of the browser’s Local Storage.
At some point, however, we inadvertently execute const a = new B(); a.storageData(); The getTaskList1 interface requests that the data be cached in the taskData of the browser’s Local Storage, replacing the taskData value in the browser’s Local Storage. There is an error in using the taskData in the browser’s Local Storage in the program.
If the Richter substitution principle had been followed during development, this would not have happened at all. Const a = new a (); Const a = new B(); After the program can run normally. When subclass B inherits from parent class A, it changes the storageData method in parent class A, causing the program to fail to run properly.
Therefore, the Richter substitution principle has a more general definition: a subclass can extend the function of the superclass, but cannot change the original function of the superclass.