preface
đ˘ Blog debut: Hiro’s blog
â This article does not talk about dry theory, directly say this design pattern is what, when to use, what scenario to use, and additional real cases
đ this article combined with xiao brother to share the PPT content, after sorting out + self-understanding, the final output of this blog, team gold address: Suge team
I don’t know if anyone is as confused about design patterns as I am. Take me for example. To tell you the truth, I really believe that “mountain is mountain”, “water is water” and “theory is theory”. Before graduation, I made things/projects by myself with little design thought. Old husband just don’t care so much, directly shuttle ha, But, because of this, it leads to design defects, code implementation defects, for the later maintenance, development iteration, bring trouble.
It’s true. One of the things that you need to do to move up the hierarchy is to master design patterns. I’m kidding. I really want to learn, so, after work, also have to see “JavaScript design Mode”, but really only grasp some theoretical knowledge, not the actual combat.
It is not that I do not want to practice, but I did not form this subconscious mind, not in daily development, can think of the original logic, this core module can be designed in this way ~
Two days ago, xiao brother opened a group of internal sharing, sharing the theme: “front-end design mode”, after listening to the sharing, well, a word woke up the dreamers, this is not warm, hurry to record
What do you learn after reading this article?
First of all, I can’t guarantee what you can gain, and then this is what I listened to share, including combining with my own understanding, and then summed up, more is, combined with actual scenarios, real cases, let everyone to understand the original design pattern is around us, in our daily development ~
- The main speak
- The strategy pattern
- Publish and subscribe
- Decorator pattern
- Adapter mode
- The proxy pattern
- Chain of responsibility model
This article is suitable for people
- đ melon eating masses
- Introduction to Design patterns
- Not sure how design patterns are used in your project
- Just like me, he’s a piece of shit
- .
The text start
Although before I say not to talk dry theoretical knowledge, but, we still go through the process. Just like your blind date, you can’t just say I have a house, a car, no bad hobbies… At least a brief introduction ~
What are design patterns?
The official explanation is that a pattern is an edible solution to a common problem encountered in software design.
In plain English, is the routine, take đ°, we play greedy play blue month, your first level used half an hour, the second level used an hour, the third level used two hours….
Well, you are the strongest, you spent a month to practice to the full level, so you began to practice the second number, at this time, in fact, you already know, every level of the shortcut, good equipment where, so you follow this routine, very quickly, 20 days and practice a full number.
Have close friend to ask you how so fast again practiced a number, so you for the benefit of the public, you wrote a breakthrough strategy ~
In this example, you know what design patterns are, right? To quote the words of Brother Xiuyan: there are recipes in cooking, strategies in games, and “routines” in everything that enables us to achieve our goals. In the world of programming, “routines” in programming are design patterns.
Of course, if I had to give you a definition, I think a design pattern is a better solution to a particular problem or scenario in software design and development.
Why are there design patterns?
On the above đ°, Mr. Lu Xun once said: “There is no such thing as hope. They are like the way of the earth; In fact, there is no road on the ground, but as many people walk, it becomes a road. “Design mode is the widely recognized and effective solution proposed by predecessors to the problems encountered in development.
Why do you need design patterns?
Some of you may not have used it, or you may have used it but you don’t know it’s a design pattern. So why do we need it? Because when we encounter similar problems, scenarios, can quickly find a better way to solve
How to use it?
In JS design mode, the most core idea – encapsulation change, how to understand, such as we write a thing, this thing in the initial V1.0 is the B sample, to V5.0, V10.0 or even V99.0, V100.0 or this B sample, that OJBK, you love how to write how to write, You just have to make it happen.
The core operation of design patterns is to observe the changes and invariances in your entire logic, and then to separate the changes and invariances in order to make the changing parts flexible and the unchanged parts stable.
Design pattern classification
What are the design patterns? Believe to understand, all know there are more than 20 kinds of…
A lot. I don’t talk about that much. I haven’t used the rest. What enjoy yuan mode, appearance mode, generator mode what, I have never used, I how to talk to you ah, I today to crack a few front end commonly used.
Subject to a
Let’s do a problem first, very simple, everyone must have done permissions logical judgment, right?
Requirements: Users can only read hiro’s article if they meet the following conditions
I’ll give you 3 minutes. How do I write the code? “Oh, do you despise old husbands? The old man picked up the keyboard, is if-else soha, directly away, next!”
function checkAuth(data) {
if(data.role ! = ='juejin') {
console.log('Not a gold digger');
return false;
}
if (data.grade < 1) {
console.log('Nugget grade less than 1');
return false;
}
if(data.job ! = ='FE') {
console.log('Not front-end development');
return false;
}
if(data.type ! = ='eat melons') {
console.log('Not the melon eaters.');
return false; }}Copy the code
I’m sure everyone can write this code, so what’s the problem with writing it this way?
- The checkAuth function explodes đĽ
- Policy items cannot be reused
- Violate the open and closed principle (do not know the open and closed principle)
The smart ones already know what pattern we’re talking about here. Right! This is the strategic model. So what is the strategic pattern?
The strategy pattern
Definition: There are multiple options to implement a function. We define policies, encapsulate them one by one, and make them interchangeable.
Strategy and combination, perfect match, brother!
Let’s use the strategy mode to modify the following logic đ
// Maintain a list of permissions
const jobList = ['FE'.'BE'];
/ / strategy
var strategies = {
checkRole: function(value) {
return value === 'juejin';
},
checkGrade: function(value) {
return value >= 1;
},
checkJob: function(value) {
return jobList.indexOf(value) > 1;
},
checkEatType: function(value) {
return value === 'eat melons'; }};Copy the code
Now that we’ve written the strategy, all we need to do is verify it
// Check rules
var Validator = function() {
this.cache = [];
// Add a policy event
this.add = function(value, method) {
this.cache.push(function() {
return strategies[method](value);
});
};
/ / check
this.check = function() {
for (let i = 0; i < this.cache.length; i++) {
let valiFn = this.cache[i];
var data = valiFn(); // Start the check
if(! data) {return false; }}return true;
};
};
Copy the code
At this time, Xiao Peng needs to perform permission verification under the following conditions:
- The nuggets user
- Gold mining grade 1 or above
The code would then look something like this:
// Xiao Peng uses the policy mode to operate
var compose1 = function() {
var validator = new Validator();
const data1 = {
role: 'juejin'.grade: 3
};
validator.add(data1.role, 'checkRole');
validator.add(data1.grade, 'checkGrade');
const result = validator.check();
return result;
};
Copy the code
Then another little friend hiro, he may need to perform permission verification conditions:
- The nuggets user
- Front end engineer
The code would then look something like this:
// Hiro uses policy mode to operate
var compose2 = function() {
var validator = new Validator();
const data2 = {
role: 'juejin'.job: 'FE'
};
validator.add(data2.role, 'checkRole');
validator.add(data2.job, 'checkJob');
const result = validator.check();
return result;
};
Copy the code
Isn’t that much better than writing crazy if-else all the time? What other examples? Form validation for form fields (name, password, email,….) We can use the strategy mode to design and optimize it. What do you think? I’ve been teaching you this far
When to use strategic mode?
When you are responsible for modules that basically meet the following conditions
- The policies under each judgment condition are independent and reusable
- The internal logic of the policy is relatively complex
- Policies need to be flexibly combined
Topic 2
Before also force a little bit, here directly to the demand đ
Requirement: After the application is successful, the corresponding logic of the order, message, and approval module needs to be triggered
What would I do if I were smart?
function applySuccess() {
// Notify the message center to get the latest content
MessageCenter.fetch();
// Update order information
Order.update();
// Notify relevant parties for review
Checker.alert();
}
Copy the code
Don’t write like this, still want zha drop!! Yeah, that’s fine, but let’s think about a couple of things
For example, messagecenter.fetch () was written by Peng, and his uncle came and got upset. He changed the module’s method name to Messagecenter.request ()
For example, you again and the parallel development of the wide, wide module is responsible for Order, the same you write the code, then run, error, one asked, found that the original width o go to the disco dancing last night, originally should be done today Order. The Order module update (), delayed a day, that you can only comment code first, after the dependent module development. You can go back and add the logic
What’s more frightening is that you may not only involve these three modules, maybe there are many more modules. For example, you have successfully applied, and now you need to report the application log. You can’t write like this, can you?
function applySuccess() {
// Notify the message center to get the latest content
MessageCenter.fetch();
// Update order information
Order.update();
// Notify relevant parties for review
Checker.alert();
/ / maybe moreLog.write(); . }Copy the code
At this point, our publish-subscribe model is starting to get ugly.
Publish and subscribe
Ahem, this is an EventEmitter. It’s often put out in interviews.
Publish-subscribe is a message paradigm in which the publisher of a message, instead of sending the message directly to a specific subscriber, broadcasts the message over a message channel, and subscribers then subscribe to get the message they want.
Let’s modify the above code below with a publish-subscribe model đ
const EventEmit = function() {
this.events = {};
this.on = function(name, cb) {
if (this.events[name]) {
this.events[name].push(cb);
} else {
this.events[name] = [cb]; }};this.trigger = function(name, ... arg) {
if (this.events[name]) {
this.events[name].forEach(eventListener= > {
eventListener(...arg);
});
}
};
};
Copy the code
We have written an EventEmit above, and then our business code can be changed to this ~
let event = new EventEmit();
event.trigger('success');
MessageCenter.fetch() {
event.on('success'.() = > {
console.log('Update message Center');
});
}
Order.update() {
event.on('success'.() = > {
console.log('Update order information');
});
}
Checker.alert() {
event.on('success'.() = > {
console.log('Notify administrator');
});
}
Copy the code
But is that okay? There are drawbacks, such as excessive use of publish and subscribe, which makes it difficult to maintain the calling relationship. So, let’s look at your design, just to let you know what the publish and subscribe model is
When to use a publish-subscribe model?
When you are responsible for modules that basically meet the following conditions
- Each module is independent of each other
- There are one-to-many dependencies
- Dependent modules and dependencies are unstable
- Each module is developed by different personnel and teams
I know you have questions about the observer vs. publish/subscribe model. I won’t go into the distinction here, but I’ll talk about it next time, or check your own data
The title three
This topic, also a little hard to think of ah, I directly say, mainly talk about the decorator pattern, adapter pattern.
Decorator pattern
To empower a function, to enhance its ability to dynamically add the behavior of an object, so I pass in an object
In the JS world, everything in the world is an object
We will buy orange trees for the Chinese New Year (those who do not buy will be taken away), which means “good luck and great prosperity”. So after we buy orange trees, we will hang some red envelopes on them and turn into “red envelope orange trees”. The red envelope here is the decorator, it does not affect the original function of the orange tree.
Take đ° for example. I am writing this article now, I can only write Chinese, but there are British friends among you, I can’t write English, so I need a decorator to give me the ability to write English
You’re not actually writing code here. Can you give me an example of đ° that you develop everyday? Ok, let me give you an example of a higher-order component HOC in React
If you know React, a higher-order component is a function that takes a component as an argument and returns a new component.
So let’s now write a high-level Component, HOC, and decorate the Target Component with it
import React from 'react';
const yellowHOC = WrapperComponent= > {
return class extends React.Component {
render() {
<div style={{ backgroundColor: 'yellow' }}>
<WrapperComponent {. this.props} / >
</div>; }}; };export default yellowHOC;
Copy the code
Defines a high-level component with a decorative yellow background that we use to decorate the target component
import React from 'react';
import yellowHOC from './yellowHOC';
class TargetComponent extends Reac.Compoment {
render() {
return <div>66666</div>; }}export default yellowHOC(TargetComponent);
Copy the code
You see, we are using decorator mode, right? What, you don’t get it? So let me give you one last example, and I don’t know if that will help you understand
const kuanWrite = function() {
this.writeChinese = function() {
console.log('I can only write Chinese');
};
};
// Add the ability to write English to Hiro via the decorator
const Decorator = function(old) {
this.oldWrite = old.writeChinese;
this.writeEnglish = function() {
console.log('Give Hiro the ability to write English.');
};
this.newWrite = function() {
this.oldWrite();
this.writeEnglish();
};
};
const oldKuanWrite = new kuanWrite();
const decorator = new Decorator(oldKuanWrite);
decorator.newWrite();
Copy the code
Adapter mode
Personally, to solve our incompatibility problem, replace the interface of a class with the interface we want.
Take đ° for example. When I want to listen to music, I find that I do not bring headphones. My mobile phone is an iPhone, but now I only have a Type-c headphones.
Let me give you an example from a real business. I had to do a requirement a while back, and it went like this.
If you look at this diagram, the red box in the diagram is a resource list display component. The data in this list can be obtained from three sources: local upload, resource list addition, and resource return in the background.
How do you understand that? As can be seen in the figure, the process is mainly:
- The resource Summary on the right is the call interface and returns a MaterialsList that can be added from the right by clicking +
- You can also select a local file to upload
- In the case of editing, there is also data returned by the background interface
These three data formats are different due to historical reasons and previous problems with the data structure returned by the backend interface.
// The data structure after the local resource file is uploaded
export interface ResourceLocalFileType {
uuid: string;
name: string;
size: number;
created: number;
lastModified: number;
resourceType: number;
cancel: () = > void;
status: string;
}
Copy the code
// The data structure returned by the resource Summary interface
export interface ResourcePackageFileType {
uuid: string;
materialName: string;
materialLink: string;
materialType: number; uid? :string; ext? :string;
}
Copy the code
// The data interface returned by the original data background
export interface ResourceBackendFileType {
uuid: string;
resourceName: string;
resourceLink: string;
resourceType: number;
version: string;
ext: string;
}
Copy the code
Our resource list component is a list that can only receive one data format. I don’t want to break the internal logic of a pure display component. I want to keep the component’s job: display!
So how do we deal with that? Adaptor mode is adopted to adapt different data structures to the data structures that can be accepted by the presentation components
First, define a uniform data format: AdapterResourceFileType
export interface AdapterResourceType {
uuid: string;
created: number;
fileNo: number;
fileName: string;
fileOrigin: string;
fileStatus: string;
fileInfo: {
type: number; size? :number;
[key: string] :any;
};
// Local image extra operationaction? : { cancel? :() = > void;
[key: string] :any;
};
}
Copy the code
And then through the adapter module, we need to adapt the interface API.
When the data is presented as a list of components, the data from different sources is processed by the adapter, consolidated, and passed to the presentation components for our purposes
You might think, this is the adapter, right? Are you kidding me? I would like to say: _________
The title four
Let’s talk about another model called the agency model. When it comes to agency, the first word that comes to mind is “event delegation, event agency”. Does that count? Calculate the dalai. Let me give you some đ° to let you know what the agent mode is
As a programmer, it’s hard to find a girlfriend, and even if I did, I’m too weak to protect me, so I paid for a bodyguard to protect me. It’s safe. This is the agency model.
Did you do that? Can you Google? Honest man which will what turn qiang, I will not, will I also said I will not. In fact, normally speaking, our direct access to Google is unresponsive. So what do we do? We use a third-party proxy server. A small plane? Understand?
To say junior high school non-mainstream three giants, than Xu Song, Xu Liang, Wang Sulong, want to go to see Xu Song concert last year, good guy, the concert tickets have been robbed, helpless, can only find scalpers, here, scalpers play the role of agent, understand?
The same is true of agents in the program world. We do not directly operate on the original object, but do so by proxy. The agent’s role is to preprocess or forward our request to the actual object.
Proxy mode is to provide a proxy for other objects to control the access of the this object, the function of the specific implementation or the object itself, for example, we email, through the proxy pattern, so can control agents, decide whether to send or not hair, but the specific executive function, are determined by the external object, rather than decision agents.
// Send emails, not qq mailbox interception
const emailList = ['qq.com'.'163.com'.'gmail.com'];
/ / agent
const ProxyEmail = function(email) {
if (emailList.includes(email)) {
// Mask processing
} else {
// Forward to send email
SendEmail.call(this, email); }};const SendEmail = function(email) {
// Send mail
};
// External invocation proxy
ProxyEmail('cvte.com');
ProxyEmail('ojbk.com');
Copy the code
Here’s another example, from JavaScript Design Patterns and Development Practices
/ / ontology
var domImage = (function() {
var imgEle = document.createElement('img');
document.body.appendChild(imgEle);
return {
setSrc: function(src) {
imgEle.src = src;
}
};
})();
/ / agent
var proxyImage = (function() {
var img = new Image();
img.onload = function() {
domImage.setSrc(this.src); // Set the actual image SRC after the image is loaded
};
return {
setSrc: function(src) {
domImage.setSrc('./loading.gif'); // Set the image SRC to loading
img.src = src;
}
};
})();
// External call
proxyImage.setSrc('./product.png');
Copy the code
When to use proxy mode?
When you are responsible for modules that basically meet the following conditions
- Modules have single responsibility and are reusable
- The interaction between two modules requires some limiting relationship
Here I know you have a question, about the proxy mode VS decorator mode, HERE I do not talk about their distinction, next time to talk, or their own data query
Topic five
Requirements: As shown in the figure, after we apply for the equipment, we need to select the delivery address and then the responsible person, and the last one must be successful before the next ~ can be executed
Friends are surprised, isn’t it easy? The force to!
function applyDevice(data) {
// Handle bala...
let devices = {};
let nextData = Object.assign({}, data, devices);
// Perform the selection of shipping address
selectAddress(nextData);
}
function selectAddress(data) {
// Handle bala...
let address = {};
let nextData = Object.assign({}, data, address);
// The execution selects the responsible person
selectChecker(nextData);
}
function selectChecker(data) {
// Handle bala...
let checker = {};
let nextData = Object.assign({}, data, checker);
// And more
}
Copy the code
You see, this is not done, what is difficult, and then the next day, you have two new process requirements, one may have two steps, one may have more “check inventory” step
You are not surprised, oh mama ah, old husband chat hair teenager crazy, keyboard wait on, Ctrl C + Ctrl V, direct copy and change the logic??
Here is the chain of responsibility pattern.
Chain of responsibility model
What is the chain of responsibility pattern? I gave you a definition: avoid coupling the sender of a request with the receiver, make it possible for multiple objects to receive the request, link those objects into a chain, and pass the request along the chain until an object processes it.
const Chain = function(fn) {
this.fn = fn;
this.setNext = function() {}
this.run = function() {}}const applyDevice = function() {}
const chainApplyDevice = new Chain(applyDevice);
const selectAddress = function() {}
const chainSelectAddress = new Chain(selectAddress);
const selectChecker = function() {}
const chainSelectChecker = new Chain(selectChecker);
// Use the chain of responsibility pattern to implement the above function
chainApplyDevice.setNext(chainSelectAddress).setNext(chainSelectChecker);
chainApplyDevice.run();
Copy the code
What are the benefits? First of all, you decouple the nodes, so the way you did it before was you put B in A and C in B, but this is different, you can put nothing in B.
Second, the nodes can be split and reassembled flexibly, just like the two new requirements you connect to above. For example, two steps you just have to do it this way
const applyLincense = function() {}
const chainApplyLincense = new Chain(applyLincense);
const selectChecker = function() {}
const chainSelectChecker = new Chain(selectChecker);
// Use the chain of responsibility pattern to implement the above function
chainApplyLincense.setNext(chainSelectChecker);
chainApplyLincense.run();
Copy the code
When to use the chain of responsibility pattern?
When you are responsible for modules that basically meet the following conditions
- Are you in charge of a whole process, or are you in charge of only one part of the process
- Each link can be reused
- Each link has a certain order of execution
- Each link can be reorganized
At the end
Before you know it, and give you lu an article on the design patterns, design patterns are really important, although I also just understand a little trick, but I think that there may be a lot like me, outside the threshold of design patterns, delays in insight to a friend, I am a tired look long, before also looked at the design pattern books, When I first read it, I could read it patiently, but when I read other people’s blogs and articles, I came across many definitions and theories, including some examples of đ°. I felt I understood it at that time, but in the development, I still didn’t know how to use it…
It’s not about forcing people to adopt design patterns, it’s about saying: First of all, we need to understand, and secondly, we need to form a kind of muscle memory. Just like the example of strategy pattern and publish and subscribe pattern mentioned above, everyone will encounter it in real development scenarios, but did not think that this is the design pattern, or it can be used to design.
Three questions from this article, including Xiao brother share the PPT, and mind mapping as well as the painting of his, after his permission, I will be finishing has become an article, combining with my own understanding at the same time, as far as possible in the form of a kind of humor, funny, and easy to understand, to be, be a Lao if I had said the wrong place or misunderstandings, Welcome to point out ~ Thank you ~
By the way, a few days ago wrote a front-end slag I dare not say I will write Button component article, and then found that was transferred to the private public number, if not for the students told me, I do not know the original my article was the public number marketing to transfer. Although the note of the original source, but still want to say, you turn my article, at least in the comment area will notify it ~
Read my article friends all know that, I was almost a month to a blog or two more, not I don’t want to update, but I want to do is have a dynamic life, is really have to know, to do practice, go to the source code, and then, word by word in the computer desk, into an article is to have a little help, write this article, May need me an afternoon or even a day of time, you good, direct Ctrl C + Ctrl V, copy my article in the past, and then post a link to the original, I…
I am not not to allow you to turn, you at least inform me a ~ I: ďźďźďźďźďźďźďź
Forget it, do not say, thank the reader to see here, the source code I put here design mode demo source code, want to see self ~
A link to the
- Hiro’s blog
- Scotland team
More articles
- ăKTă Easy to get Redux source code interpretation and programming art
- ăKTă Build your own front-end knowledge system
- I can’t say I can write Button components anymore