preface
Mention of design patterns may feel a little lofty feeling, in fact, the concept of this thing is very abstract, but in actual development, there are still many places can use the idea of design patterns, to optimize our code. The purpose of this article is to introduce some common design patterns in development, learn by example, and try to skip over the concepts. In order to get the adoring eyes of the little elder sister next door, learn together!
The body of the
1. Adapter mode
Concept: transform the interface of one class into another to meet user needs, so that incompatibilities between the interfaces of classes (objects) can be resolved through adapters.
At work, there are times when a new module needs to be compatible with an old module in order to meet requirements, and the adaptor pattern is needed.
Such as:
- Method passes parameters by default
Function doSomeThing(obj){const adapter = {name:" default name ", color:"red", size:200, age:20 } for (let i in adapter){ adapter[i] = obj[i] || adapter[i]; } // do some thing }Copy the code
And you can see that by doing this we can make sure that we have these properties in the object no matter what parameters we pass in. Avoid subsequent logic errors.
- Global encapsulation method extension and compatibility.
In vUE usage, we usually mount API requests on vue instances, but some older projects are done by encapsulating Ajax requests, and refactoring old projects requires all API requests to be placed on axios or fetch. This allows the adapter pattern to be used.
Export default class FetchApi{static get(URL){return new Promise((resolve,reject)=>{ fetch(url).then(...) .catch(err=>reject(err)) }) } static post(url,data){ return new Promise(...) }} / / when we use so we use the const res = await FetchApi. Get (url) | | {}; / / or const res = await FetchApi. Post (url, params) | | {} / / look at the original way of interface encapsulation Pseudo code function Ajax (type, url, data) {const XHR = new XMLHttpRequest() ... if(type === 'GET'){ xhr.open('GET',url+"?" +data,true); xhr.send() }else if(type === 'POST'){ xhr.open('POST',url,true); xhr.setRequestHeader("Content-type",'application/x-www-form-urlencoded') xhr.send(data) } ... } // Call Ajax("GET", URL,data)Copy the code
Here we can see that the new and old interfaces have different interface names and request pass parameters. That’s ok, use the adapter.
/ / pseudo-code async function ajaxAdapterr (type, url, data) {let result if (type = = = 'GET') {result = await FetchApi. GET (url) | | {} }else if(type === 'POST'){ result = await FetchApi.post(url,data) || {} } } async function Ajax(type,url,data){ await ajaxAdapterr(type,url,data); }Copy the code
This allows you to change the original Ajax requests to the FETCH, instead of modifying the requests one by one in the page. Save a lot of time can be used to touch fish.
2. Policy mode
Concept: Encapsulate a defined set of algorithms so that they are interchangeable with each other. The encapsulated algorithm is independent and does not change with the client.
Concepts are good at describing things that everyone understands that adults don’t. Let’s look at the actual scene.
In your work, I’m sure you’ve written many, many if else judgments. When there are more and more conditions, this kind of writing will become very bloated, so use strategy mode to optimize.
Such as:
function doSomeThing(type){ if(type === 'pre'){ return 100 }else if(type === 'onSale'){ return 200 }else if(type === Else if(type === 'fresh'){return 250}} function doSomeThing(type){const priceType = { pre(){ return 100 }, onSale(){ return 200 }, back(){ return 150 }, fresh(){ return 250 } } return priceType[type]() }Copy the code
As you can see, after using the policy pattern optimization, the mapping relationship of the code is clear and more flexible and intuitive, and later maintenance only needs to add methods to the object. Handsome is a word, I only say once. Such code which front end little elder sister looked not to say great?
3. Status mode
Concept: When an object’s internal state changes, it causes its behavior to change, which appears to change the object.
The state pattern is similar in concept to the policy pattern in that it encapsulates behavior and distributes behavior through delegation. However, the methods distributed in the strategy mode are not dependent, parallel to each other, and water does not invade the river. In state mode, there is a certain correlation between the functions and the subject.
Such as:
Automatic coffee machine
Class Coffee{constructor(){this.state =' constructor '; } stateProcessor = {American: () = > {the console. The log (" black coffee ")}, places: () = > {this. StateProcessor. American (); / / to make black coffee console. The log (" white ")}, vanillaLatte: () = > {this. StateProcessor. Places (); The console. The log (" add vanilla 🌿 syrup ")}, mocha: () = > {this. StateProcessor. Places (); Console. log(' add chocolate 🍫')}} changeState(state){this.state = state; if(! This.stateprocessor [state]){return console.log(" no coffee ")} this.stateprocessor [state]()}} const coffee = new coffee (); coffee.changeState("latte")Copy the code
The state pattern mainly addresses situations where the conditional expression governing the state of an object is too complex. The complex judgment logic can be simplified by moving the state judgment logic to a series of classes representing different states.
4. Proxy mode
Concept: Since an object cannot reference another object directly, a proxy object is used to mediate between the two objects.
The proxy is something that you might be involved in your development, but I’m not going to talk about the basic proxy, but I’m going to talk about the caching proxy
For example, sum the incoming parameters
Const addAll = function() {console.log(' a new calculation was performed ') let result = 0 const len = arguments.length for(let i = 0; i < len; I ++) {result += arguments[I]} return result} const proxyAddAll = (function(){// sum result cache pool const ResultCache = {} return function () {/ / convert into the reference to a unique into the parameter string const args = Array. The prototype. Join. The call (the arguments, If (args in resultCache) {// If (args in resultCache) { Return resultCache[args]} return resultCache[args] = addAll(... arguments) } })()Copy the code
As you can see, in the case of consistent input parameters, only one calculation is done, and all subsequent values are returned from the cache, which is a great time saver in the case of very heavy computation.
5. Decorator mode
Concept: An object can be made to meet more complex requirements by wrapping an extension (adding properties or methods) without changing the original object.
For example, in the approval flow, the original requirement is that the approval passes and rejects are processed together, and the later requirement is added, and a pop-up box is required to input the reason for the rejection when the rejection is made
Function approvalOrReject(){// do some thing} function rejectShowBox(){this.approvalOrReject(); this.showMessageBox(); // Display popup frame}Copy the code
In this way, we have implemented the “add, don’t modify” decorator pattern. The decorator pattern is especially useful in actual development, and you can find it with your heart
summary
Summarize these design patterns for the time being, and we will continue to sort out and add them in the future. Please like them and collect them
Since using the design mode, the little sister began to nod to me, brothers, use it.
As my level is limited, if there is any mistake in the text, please contact me.