Hello, everyone! I make milk tea without sugar. A front-end siege lion who likes drinking milk tea (haha, today is also a day to move bricks (* ̄))😁😁😁
preface
🙌 there are many partners in the process of learning JS, will feel that the design pattern is more difficult, but it is the only way we advanced, but also in order to let us write better, better and faster code, so I summarized several commonly used design patterns, together to see ba ba ba 💪💪💪
What are design patterns
Let’s say we have an empty room and we have to put something in it day after day. The easiest way, of course, is to throw these things in, but after a long time, you will find it difficult to find what you want in the house, and it is not easy to adjust the location of certain things. So maybe it’s better to have some cabinets in the room. Although the cabinets will increase our cost, they will benefit us in the maintenance phase. The rules for storing things in these cabinets may be a pattern
The principle of learning design patterns to write reusable and maintainable programming patterns is to “identify and encapsulate changes in your program.” It’s about intent, not structure. Be aware, however, that improper use of words, may be half the result.
I. Factory model
Factory mode: Factory mode is similar to factories in real life, which can produce a large number of similar goods to do the same thing and achieve the same effect. You need to use the factory pattern. The simple factory pattern can be understood as solving multiple similar problems; That’s one of her strengths;
For example: get the desired content from the factory function
function creatPerson(name) {
// Create the desired object
var obj = {};
// Add the necessary data to the object
obj.name = name;
// Return the created object
return obj;
}
Copy the code
Advantages: Simplify the operation of creating objects, just need to call the function can get objects disadvantages: can not determine the ownership of objects
var obj1 = creatPerson('ning elder brother');
console.log(obj1 instanceof creatPerson);// --> false
console.log(obj1 instanceof Object);// --> true
Copy the code
2. Singleton mode
Singleton mode: Objects created by singletons are initialized (instantiated) only once, and the objects obtained by subsequent calls to the creation method are always the objects created by the first call
function CreatePerson(name){
this.name = name;
}
CreatePerson.prototype.sayHi = function(){
console.log("hello");
}
Copy the code
1. Call internal functions inside functions without using closures
This doesn’t make sense because it still creates many different objects each time the function is called
var person = null;// Write this globally, which is bad for code structure
function SingalPerson(){
var person = null;
function aaa(name){
if(! person){
person = new CreatePerson(name);
}
}
aaa(name)
console.log(person);
// When the function returns, there is no person left in the function
return person;
console.log(person);
}
var a = SingalPerson();
console.log(a);
Copy the code
2. Using closures means that the person will not be destroyed after being returned, but will remain in memory
A function that creates an object
function SingalPerson(){
var person = null;
return function(name){
if(! person){
person = new CreatePerson(name);
}
return person;
}
}
Copy the code
Although you can call SingalPerson() in one step; You can achieve a singleton effect, but if two objects are created inside a function, you need to call SingalPerson twice in each function. You could also write the expression that calls SingalPerson() globally, so that the variable that holds the result of SingalPerson() can be called every time you create an object, but this would split the SingalPerson into two parts, which is not very logical and structural for the program
var a = SingalPerson();
var obj1 = a("haha");
console.log(obj1);
// We can see the effect of singletons
var obj3 = a("lala");
console.log(obj3);
SingalPerson() creates two different objects if executed twice
//var b = SingalPerson();
//var obj2 = b("lala");
//console.log(obj2);
Copy the code
3. Use closures and execute function implementations immediately
To execute the outer function only once, you can use the self-call, so that you don’t have to define the global function outside, when the program runs to this line of code immediately execute the function, and then use a variable to hold the result of the function, and then you can call the variable outside, Because the outside function returns the inside function that we’re executing over and over again
var aa = (function SingalPerson(){
var person = null;
return function(name){
if(! person){
person = new CreatePerson(name);
}
return person;
}
}) ();
var obj1 = aa("haha");
console.log(obj1);
var obj2 = aa("lala");
console.log(obj2);
Copy the code
In all three ways, the singleton pattern is still optimal using closures and executing functions immediately
4. Instances of singleton patterns
Common scenarios of singletons
Only need to generate a single object, such as login page, there may be a login box, only then you can use the singleton thought to realize him, of course you don’t have the thought of the singleton implementation, the result may be that every time you to display the login box to regenerate a login box and display (cost performance), Or accidentally displaying two login boxes (expect to eat the manager’s 40m knife), hee hee hee.
The singleton pattern implements the modal window
var creatDiv = (function(){
var div = null;
// The return function is the actual operation used to create labels and concatenate labels
return function() {
if(! div) {// Check if the tag exists, create it if it does, and return it if it does
div = document.createElement('div');
div.setAttribute('style'.'width: 100px;
height:100px; border:1px solid black');
document.body.appendChild(div);
}
return div;
}
}) ();
// Add click events after the page is loaded
window.onload = function () {
document.getElementById('btn').onclick = function () {
var divElement = creatDiv();
divElement.style.display = 'block';
divElement.onclick = function() {
document.body.removeChild(divElement);
divElement.style.display = 'none';
}
}
}
Copy the code
3. Agency mode
Proxy is an object, it can be used to control the access to the ontology object, it and the ontology object to achieve the same interface, the proxy object will pass all call methods to the ontology object; The most basic form of proxy mode is to control access, while ontology objects are responsible for executing the functions or classes of the assigned object. Simply speaking, local objects focus on executing the code on the page, while proxies control when local objects are instantiated and when they are used. We have used some proxy patterns in the singleton pattern above, which is used to instantiate the singleton pattern, leaving ontology objects to handle the rest.
✅ agent has two advantages:
- Proxy objects can be instantiated instead of ontologies and made accessible remotely;
- It can also delay ontology instantiation until it is really needed; We can defer instantiation of ontology objects that take time to instantiate or are too large to be kept in memory when not in use
The first option: the preloading image function without a proxy is as follows
// The preload image function without proxy is as follows
var myImage = (function(){
var imgNode = document.createElement("img");
document.body.appendChild(imgNode);
var img = new Image();
img.onload = function(){
imgNode.src = this.src;
};
return {
setSrc: function(src) {
imgNode.src = "http://img.lanrentuku.com/img/allimg/1212/5-121204193Q9-50.gif";
img.src = src;
}
}
}) ();
Copy the code
Call way myimage.png setSrc (” https://img.alicdn.com/tps/i4/TB1b_neLXXXXXcoXFXXc8PZ9XXX-130-200.png “);
The second option: use proxy mode to write the code for preloaded images as follows:
var myImage = (function(){
var imgNode = document.createElement("img");
document.body.appendChild(imgNode);
return {
setSrc: function(src) {
imgNode.src = src;
}
}
}) ();
// Proxy mode
var ProxyImage = (function(){
var img = new Image();
img.onload = function(){
myImage.setSrc(this.src);
};
return {
setSrc: function(src) {
myImage.setSrc("http://img.lanrentuku.com/img/allimg/1212/5-121204193Q9-50.gif");
img.src = src;
}
}
}) ();
Copy the code
Call way ProxyImage. SetSrc (” https://img.alicdn.com/tps/i4/TB1b_neLXXXXXcoXFXXc8PZ9XXX-130-200.png “);
Myimage.setsrc is used to create a preloaded image for the image. When the image is loaded, the img element is assigned to the image. The second method is implemented using proxy mode. The myImage function is only responsible for creating the IMG element, and the proxy function ProxyImage is responsible for loading the image. When the image is loaded, the myimage.setsrc method in myImage is called to set the path of the image.
Their advantages and disadvantages are as follows:
- In the first approach, the code is usually too coupled, with a function that does several things, such as creating the IMG element and implementing Settings for the image before it is loaded
loading
Loading state and many other things, did not meet the single responsibility principle of object-oriented design principle; And when the proxy is not needed at some point, it needs to be frommyImage
Get rid of the code inside the function because it’s too coupled. - The second uses proxy mode, where the myImage function does only one thing, create
img
Element is added to the page, which is loadedloading
The image is given to the proxy functionProxyImage
When the image is loaded successfully, the proxy functionProxyImage
Will be notified and implementedmyImage
Function method, and when we do not need the proxy object in the future, we can directly call the ontology object method;
As you can see from the above proxy mode, the proxy mode and ontology object have the same method setSrc, which has the following two advantages:
- Users can safely request the broker, and all they care about is getting the results they want. If we do not need a proxy object, we can simply call this method with an ontology object.
- Anywhere an ontology object is used it can be replaced with a proxy.
4. Observer mode
Observer pattern: Publish – subscribe pattern is also known as the observer pattern, it defines a one-to-many relationship between objects, let multiple observer objects listen to a subject object, when an object changes, all dependent objects will be notified.
Advantages of ✅ publish subscribe model:
- Supports simple broadcast communication that automatically notifies subscribed objects when their state changes.
- The coupling between the publisher and the subscriber is reduced. The publisher only releases a message, and it does not care how the message is used by the subscriber. At the same time, the subscriber only listens to the event name of the publisher, and it does not care how the publisher changes as long as the event name of the publisher remains unchanged.
Disadvantages of ❌ publish subscribe model:
Creating subscribers takes time and memory. Although it can weaken the connection between objects, if overused, it will make the code difficult to understand and maintain, etc.
- Start by figuring out who the publisher is (i.e., the seller above).
- The publisher is then given a cached list that holds a callback function to notify the subscriber (the buyer bookmarks the seller’s store, and the seller bookmarks a list of that store).
- The last step is to publish a message, which the publisher traverses through the cached list, triggering the subscriber callback function it holds in turn.
We can also add a few parameters to the callback function
var saleHouse = {};/ / publisher
saleHouse.clientlist = [];// List of customers
saleHouse.listen = function(client){// Register notified customers and place them in the list
// this.clientlist.push(client); //
console.log(this.clientlist)//[] salehouse.clientList
saleHouse.clientlist.push(client)
}
saleHouse.trigger = function(){/ / send notification
for(var i = 0,s; s =this.clientlist[i++];) {// The same way we usually write
s.apply(this.arguments);// Call the function with arguments using apply
}
}
saleHouse.listen(function(position,price){
console.log('location:+position+"Prices."+price)
})
saleHouse.trigger('Front Bay'.'120000')
Copy the code
5. Adapter mode
Adapter pattern: Translate the interface of an object or class into another interface that can be used by a given system.
Adapters basically allow objects or classes that would otherwise not work together due to incompatible interfaces to work together. An adapter translates calls to its interface into calls to the original interface, and the code that does this is usually the simplest.
The above adapter is also required for each different object (face mode)
After the language
Hope to see here friends can move a thumbs-up 👍 oh, your support is the biggest encouragement to me 💪💪💪!!