1. Background
Design pattern is a set of code design experience that is repeatedly used, known by most people, classified and summarized
Its purpose is to make the code reusable, make the code easier to be understood by others, and ensure the reliability of the code
It is a solution, and the focus is thought. The purpose is to make the code simpler, concise, reliable, easy to understand and reuse, that is, it is often said to be high cohesion and low coupling
2. What are the basic principles?
The basic principles of design patterns in javascript are as follows:
- Single responsibility principle
- Minimum knowledge principle
- Open and closed principle
- Dependency Inversion Principle
Single responsibility principle
A class is only responsible for the corresponding responsibilities in a functional field. In javascript, there are not many scenarios for using classes, and the single responsibility principle is more applied to objects or methods
If a method takes on too many responsibilities, the more likely it is that it needs to be rewritten during the change of requirements
The single responsibility principle is the simplest and most difficult principle to correctly apply. It should be clear that not all responsibilities should be separated one by one: for reference Singleton mode of design mode
- If two responsibilities always change at the same time as the needs change, there is no need to separate them
Like in ajax When requested, create xhr Object and send xhr Requests are almost always together, Then create xhr Responsibility and sending of objects xhr There is no need to separate the responsibilities of the request
Minimum knowledge principle
Objects (functions, modules, etc.) should interact with other entities as little as possible
When designing a program, you should minimize the interaction between objects. If there is no direct communication between two objects, the two objects should not be directly related to each other
A common approach is to introduce a third-party object (mediator) to undertake the communication between these objects. If some objects need to make requests to other objects, they can forward these requests through third-party objects.
The principles of using the least knowledge in javaScript Design patterns are:
- Mediator mode: by adding a mediator object, all related objects can communicate through the mediator object instead of referencing each other. Therefore, when an object changes, you only need to notify the mediator object
- Appearance mode: mask the complexity of a set of subsystems to users. Provide users with a simple and easy-to-use interface, and the high-level interface will forward the user's request to the subsystem to complete the specific function implementation
Open and closed principle
In object-oriented programming, the open and closed principle is the most important principle
The idea is that when you need to change the function of a program or add new functions to the program, you can use the way of adding code, but you are not allowed to change the source code of the program
- Openness refers to extension oriented Openness: the behavior of modules can be extended. When the requirements of the application change, we can make the module show new or different behavior to meet the new requirements
- Closure refers to modification oriented closure: the source code of the module cannot be violated, and no one is allowed to modify the existing source code
//Detection string //checkType('165226226326','mobile') let checkType = function(str, type) { switch (type) { case 'email': return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str); case 'mobile': return /^1[3|4|5|7|8][0-9]{9}$/.test(str); case 'tel': return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str); default: return true; } }
This method can be used, but if you want to add functions, you need to add case s inside the function, which will also make the whole API bloated, difficult to maintain and violate the closed and open principle
It can be transformed as follows:
let checkType = (function() { let rules = { email(str) { return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str); }, mobile(str) { return /^1[3|4|5|7|8][0-9]{9}$/.test(str); }, tel(str) { return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str); }; //Exposed interface return { //check check(str, type) { return rules[type] ? rules[type](str) : false; }, //Add rule addRule(type, fn) { rules[type] = fn; } } })();
Dependency Inversion Principle
High level modules should not rely on low-level modules. They should all rely on abstraction. Abstraction should not rely on concrete implementation, and concrete implementation should rely on abstraction
For example, people can eat rice, steamed bread, noodles, etc. people here are high-level modules. People need to rely on eating behavior to live
Eating behavior is an abstract behavior, which can be rice, steamed bread and so on
Instead of becoming human, we should rely on eating rice or steamed bread
This reduces the coupling between the customer and the implementation module
// Eat abstract classes class eat { go(name) { return `eat ${name}` } } //Implementation class (details) class Rice extends eat { go() { return "eat rice" } } class Noodle extends eat { go() { return "noodle" } } //human beings class people { constructor(name) { this.name = name } gotoEat(food) { console.log(this.name, food.go()) } } const rice = new Rice() const noodle = new Noodle() const peopleA = new people("Xiao Ming") peopleA.gotoEat(rice)
summary
It is not easy to follow the open closed principle at the beginning of the program. It is necessary to predict the parts that are easy to change
Pick out the places that are most prone to change, and then construct abstractions to close these changes
When changes are inevitable, try to modify those places that are relatively easy to modify. For example, modify the configuration file instead of modifying its source code
Reference article: https://mp.weixin.qq.com/s/Uhx7GBqwhoZ5bhbi94StAA