JavaScript Design Mode for Refining Internal Work

Sensation:

Taste: plum ribs

Cooking time: 20 min

Someone asked me why I kept blogging?

To quote famous novelist Stephen King, "Start writing!Young people."

When you upgrade consumer interest to production interest, you will gradually discover the doors and magic that you didn't see before.

Cough, please drink chicken soup when it's cold~

Perhaps the design patterns described in this series of articles are often used in your work, but you don't know their names.

Once we have learned and integrated these design patterns, we can greatly enhance our programming skills, and provide us with better problem solving ideas when we meet actual business needs.

After all, our slogan is: No overtime!

In the book above, this paper introduces the structural design mode, including appearance mode, adapter mode, agent mode, decorator mode, bridge mode, combination mode and hedonic mode.

Appearance Mode Facade

Concepts: Complex subsystem interfaces can be provided with a more advanced unified interface, and underlying structure compatibility can be encapsulated uniformly to simplify user use.

This pattern is simple and easy to understand, and you must have encountered the following scenarios in your daily development.

We've been compatible with ie browsers over the years.

These common compatibility schemes belong to the appearance mode.

var getEvent = function (event) {
  return event || window.event;
}

var getTarget = function (event) {
  var event = getEvent(event);
  return event.target || event.srcElement;
}

var preventDefault = function (event) {
  var event = getEvent(event);
  if (event.preventDefault) {
    event.preventDefault();
  } else {
    event.returnValue = false;
  }
}

var stopBubble = function (event) {
  var event = getEvent(event);
  if (event.stopPropagation) {
    event.stopPropagation();     
  } else {
    event.cancelBubble = true;
  }
}

In team development, to avoid duplicate name overrides when adding click events, we use DOM2 level event handlers to bind events and add browser compatibility.

function addEvent (dom, type, fn) {
  if (dom.addEventListener) {
    dom.addEventListener (type, fn, false);
  } else if (dom.attachEvent) {
    // IE compatible (below 9)
    dom.attachEvent('on' + type, fn);
  } else {
    dom['on' + type] = fn;
  }
}

You can, of course, simplify the underlying operation by encapsulating multiple functions in a form pattern.

var T = {
  g : function (id) {
    return document.getElementById(id);
  },
  css : function (id, key, value) {
    document.getElementById(id).style[key] = value;
  },
  attr : function (id, key, value) {
    document.getElementById(id)[key] = value;
  },
  html : function (id, html) {
    document.getElementById(id).innerHTML = html;
  },
  on : function (id, type, fn) {
    document.getElementById(id)['on' + type] = fn;
  }
};

T.css('box', 'background', 'red');
T.attr('box', 'className', 'box');
T.html('box', 'This is the new addition');
T.on('box', 'click', function() {
  T.css('box', 'width', '500px');
})

The appearance mode wraps the interface, so we don't need to know the details of the interface implementation when using it, just use it according to the rules.

Adapter Mode Adapter

Concepts: Converts the interface (method or property) of one class (object) to another to meet user needs, so that incompatibility of interfaces between classes (objects) is resolved through adapters.

Adapters are very common in our daily life, for example, when traveling abroad, there are only three outlets in some countries. At this time, we need three to two plug power adapters.For example, after the iPhone7, the headphone connector became a lightning connector, and Apple provided us with an adapter to fit the round-hole headphone.

// Additional code written for the compatibility of code written by both code libraries is one type of adapter.
window.A = A = jQuery;

Adapters in jQuery

jQuery.fn.css()
jQuery core cssHook
// (In order to control the number of text, there is no code here, after reading, you can go to the official website to view it yourself)

jQuery Source Address

Parameter adapter

function doSomeThing(name, title, age, color, size, prize) {}
// It is difficult to remember the order of these parameters, so we often pass in as a parameter object
/**
* obj.name : name
* obj.title : title
* obj.age : age
* obj.color : color
* obj.size : size
* obj.prize : prize
**/
// When calling it, we should consider whether the parameters passed are complete or not, if some required parameters are not passed in
// Some parameters have default values and so on.At this point we can use the adapter to accommodate the incoming parameter object
function doSomeThing (obj) {
  var _adapter = {
    name : 'Front canteen',
    title : 'Design Mode',
    age : 24,
    color : 'blue',
    size : 100,
    prize : 99
  };
  for (var i in _adapter) {
    _adapter[i] = obj[i] || _adapter[i];
  }
  // Or extend(_adapter, obj) note: more attributes may be added at this time
  // do things
}

Many plug-ins do this for parameter configurations.

Data Adaptation

var arr = ['Front canteen', 'restaurant', 'Remember to eat on time', '9 Month 30'];

// We found that each member of the array represents a different meaning, so this data structure has poor semantics and we adapted it to an object.

function arrToObjAdapter (arr) {
  return {
    name : arr[0],
    type : arr[1],
    title : arr[2],
    data : arr[3]
  }
  var adapterData = arrToObjAdapter(arr);
  console.log(adapterData);  
  // {name:'front-end canteen', type:'restaurant', title:'remember to eat on time', data:'September 30'}  
}

Service-side data adapter

The mainstream solution now is to write the middle-BFF layer (Backend for Frontend) with node.js and process it after getting the data returned in the background.
Processing the data you want for the front end is also an adapter mode.

Differences from appearance patterns:

Rather than appearance mode, adapter mode knows the internal structure of the adapter object.

Proxy mode

Concepts: Since one object cannot directly reference another object, a proxy object is required to act as an intermediary between the two objects.

In real life, for example, when we rent a house, we can go back freely. It is a housing agency, which is also our agent.

Virtual proxies and cache proxies are the most commonly used in javaScript.

Virtual Agent

Picture loading preload

// Create ontology objects, generate img tags, and provide setSrc interfaces to the outside world
var myImage = (function() {
  var imgNode = document.createElement('img');
  document.body.appendChild(imgNode);

  return {
    setSrc: function (src) {
      imgNode.src = src;
    }
  }
})();

 // Introduce a proxy object, there will be a load.gif before the picture is loaded
 var proxyImage = (function () {
   var img = new Image();
   img.onload = function () {
     myImage.setSrc(this.src);
   }

   return {
     setSrc: function (src) {
       myImage.setSrc('loading.gif');
       img.src= src;
     }
   }
 })();
 // Get pictures through proxy
 proxyImg.setSrc('http://...');

Cache Proxy

It can provide temporary storage for some expensive operation results, and return the previous results directly if the parameters passed next time are consistent, which greatly improves efficiency and saves costs.

var computedFn = function () {
  console.log('start');
  var a = 1;
  for (var i = 0; l = arguments.length; i < l; i++) {
    a = a * arguments[i];
  }
  return a;
}

var proxyComputed = (function() {
  var cache = {};
  return function() {
    var args = Array.prototype.join.call(arguments, ',');
    if (args in cache) {
      return cache[args];
    }
    return cache[args] = computedFn.apply(this, arguments);
  }
})();

proxyComputed(1, 2, 3, 4); // 24
proxyComputed(1, 2, 3, 4); // 24

As shown above, proxy mode solves the problem of coupling between systems and high overhead of system resources.

Proxy in ES6

The Proxy constructor provided by ES6 allows us to easily use proxy mode.

// Objects to be proxied by target
// handler sets the behavior of the proxy object
var proxy = new Proxy(target, handler);

Proxy in ES6

Proxy in Vue3.0

The bidirectional data binding principle in vue3.0 uses Proxy in es6, and elegantly solves some of the issues in Proxy details to achieve perfect bidirectional binding. You can read the source code, or in the community This article This is not an expansion.

Decorator in Decorator Mode

Concepts: On the basis of not changing the original object, the original object can meet the more complex needs of users by expanding its packaging (adding attributes or methods).

Decorator for TypeScript@

Decorators are an experimental feature that may change in future releases.

Use method please move Official Documents

Suppose we have such a requirement in development that new events can be implemented through decorators without affecting the original events.

// Decorator
var decorator = function (input, fn) {
  // Get Event Source
  var input = document.getElementById(input);
  // If the event source is already bound to the event
  if (typeof input.onclick === 'function') {
    // Cached event source original callback function
    var oldClickFn = input.onclick;
    // Define new events for event sources
    input.onclick = function () {
      // Old callback function for event source
      oldClickFn();
      // Execute Event Source Add Callback Function
      fn();
    }
  } else {
    // Event source unbound event, add new callback function directly to event source
    input.onclick = fn;
  }
}

Differentiation from adapter mode:

In the adapter mode, we need to know the details of the implementation of the original method, while in the decorator mode we only know the internal details of the method when we call it, which is a protection of the functional integrity of the original method.

Bridge mode

Concept: The system changes along multiple dimensions without increasing its complexity and reaching decoupling.

var spans = document.getElementsByTagName('span');
// Bind special effects for user names
spans[0].onmouseover = function () {
  this.style.color = 'red';
  this.style.background = '#ddd';
}
spans[0].onmouseout = function () {
  this.style.color = '#333';
  this.style.background = '#f5f5f5';
}
// Bind effects for levels
spans[1].onmouseover = function () {
  this.getELementsByTagName('strong')[0].style.color = 'red';
  this.getElementsByTagName('strong')[0].style.background = '#ddd';
}
spans[1].onmouseout = function () {
  this.getELementsByTagName('strong')[0].style.color = '#333';
  this.getElementsByTagName('strong')[0].style.background = '#f5f5f5';
}
// Extract common points and decouple this from events
function changeColor (dom, color, bg) {
  dom.style.color = color;
  dom.style.background = bg;
}

// Using anonymous functions to bridge events to business logic
var spans = document.getElementsByTagName('span');
spans[0].onmouseover = function () {
  changeColor(this, 'red', '#ddd';)
}

// The dom in the changeColor method is essentially this in the event callback function, decoupling them
// We used a bridging method, the anonymous callback function.Through this anonymous callback function
// The this we get is passed to the changeColor function to fulfill the requirement
spans[0].onmouseout = function () {
  changeColor(this, '#333', '#f5f5f5');
}
// The same applies at the user level
spans[1].onmouseover = function () {
  changeColor(this.getElementsByTagName('strong')[0], 'red', '#ddd');
}
spans[1].onmouseout = function () {
  changeColor(this.getElementsByTagName('strong')[0], '#333', '#f5f5f5');
}
// If the requirements change, you just need to modify the contents of the changeColor
// Instead of going to each event callback function to modify it, add a new bridging function at the expense of

Decouple the implementation layer (such as element-bound events) from the abstraction layer (such as polishing page UI logic) so that the two parts can change independently.

Note that sometimes the addition of bridges can result in increased development costs and performance impacts.

Composite for Combination Mode

Concepts: Also known as the part-whole mode, which groups objects into a tree structure to represent the hierarchy of the "part-whole". The combination mode makes the use of individual and combined objects consistent.

Chinese Restaurant: Meal Service

The directory structure of the webpack build project

Organization Structure of Company Departments

Combinatorial patterns provide us with a clear structure of composition.Composite object classes have a unified approach by inheriting the same parent class, which also facilitates our unified management and use.

Implementation of addClass in jQuery

// jQuery 3.4.1
addClass: function( value ) {
    var classes, elem, cur, curValue, clazz, j, finalValue,
    i = 0;

    if ( isFunction( value ) ) {
        return this.each( function( j ) {
            jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
        } );
    }

    classes = classesToArray( value );

    if ( classes.length ) {
        while ( ( elem = this[ i++ ] ) ) {
            curValue = getClass( elem );
            cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );

            if ( cur ) {
                j = 0;
                while ( ( clazz = classes[ j++ ] ) ) {
                    if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
                            cur += clazz + " ";
                    }
                }

                // Only assign if different to avoid unneeded rendering.
                finalValue = stripAndCollapse( cur );
                if ( curValue !== finalValue ) {
                    elem.setAttribute( "class", finalValue );
                }
            }
        }
    }

    return this;
}

Instead of knowing the internal structure and implementation details of addClass, we can use addClass to add classes to tags.

Flyweight in hedonic mode

Concepts: Use sharing technology to effectively support a large number of fine-grained objects, avoiding the unnecessary overhead of having the same content between objects.

Core idea: Sharing fine-grained objects

Ultimate goal: to minimize the number of shared objects

In real life, the division of LOL and pesticide segments is the idea of the enjoyment mode, and the coffee type of coffee shop is also the idea of the enjoyment mode.

In our well-known chain inheritance of prototypes, when there are many instances of subclasses, subclasses can optimize memory by reusing the methods and attributes of the parent class through prototypes, which is also the idea of the hedonic model.

In addition, thread pools, database connection pools, HTTP connection pools, and character constant pools in Node.js are all enjoyable or upgraded versions.

Reference resources:

JavaScript Design Patterns Zhang Rongming

<br/>

Communication

Welcome to my Personal Public Number. Articles will be sent synchronously and a large amount of learning materials will be received free of charge in the background reply.

Your front dining hall, remember to eat on time.

Keywords: Javascript JQuery IE Programming

Added by rsasalm on Tue, 12 Nov 2019 05:18:08 +0200