The singleton pattern

Ensure that there is only one instance of a class and provide a global access point to that instance.

const Singleton = function () {}
Singleton.getInstance = (function(){
   // ES6 does not have static types. With closures, instance cannot be accessed outside functions
   let instance = null;
   return function(){
       if(! instance){ instance =new Singleton()
       }
       // Return if it already exists
       returninstance }; }) ()let s1 = Singleton.getInstance()
let s2 = Singleton.getInstance()
console.log(s1===s2)   //true
Copy the code

The factory pattern

The essence of the factory method pattern is to define an interface for creating objects, but let the class that implements the interface decide which class to instantiate. The factory method lets class instantiation be deferred to subclasses.

class Dog {  / / entity class
    run(){
        console.log('Dog')}}class Cat {   / / entity class
    run(){
        console.log('Cat')}}class Animal{  / / the factory class
    constructor(name){
        switch (name){
            case 'Dog':
                return new Dog();
            case 'Cat':
                return new Cat();
            default:
                throw TypeError('class name wrong')}}}const cat = new Animal('Cat')
cat.run()   
const dog = new Animal('Dog')
dog.run()
Copy the code

Publish and subscribe model

Defines a one-to-many dependency between objects. When the state of an object changes, all dependent objects can be notified.

// Vue2.0 responsive implementation
// Determine whether it is an object
function isObject(obj) {
    return typeof obj === 'object'&& obj ! = =null
};
/ * * *@param {*} obj* /

// The listener changes
function observe(obj) {
    if(! isObject(obj)) {return;
    }
    Object.keys(obj).forEach(key= > {
        var originValue = obj[key]
        observe(originValue)
        var dep = new Dep() // Create a dependency collection for each attribute
        Object.defineProperty(obj, key, {
            get: function() {
                // console.log('get' + originValue)
                dep.depend()
                return originValue
            },
            set: function(value) {
                if(value ! == originValue) {// console.log('set', value)
                    originValue = value
                    observe(originValue)
                    dep.notify()
                }
            }
        })
    })
}
//test
var state = {
    msg: 'hello'.mount: 10.addstr: {
        name: 'jiangyao'.age: 21}}; observe(state)// Rely on collection
function Dep() {
    this.functions = new Set()}var activeFunction = null
// Some function is using me
Dep.prototype.depend = function() {
    if (activeFunction) {
        this.functions.add(activeFunction)
    }
}

// Notify all objects that use this function: I have changed
Dep.prototype.notify = function() {
    this.functions.forEach(fn= > fn())
}

function autorun(fn) {
    function functionWrapper() {
        activeFunction = functionWrapper
        fn()
        activeFunction = null
    }
    functionWrapper()
}

autorun(() = > {
    app.innerHTML = `${state.msg}+${state.mount}`   // Add to the page
})
Copy the code
    <div id="app"></div>
    <script src="./vue responsive.js"></script>
Copy the code

The proxy pattern

Provide a proxy for other objects to control access to that object. In some cases, an object is inappropriate or cannot directly reference another object, and a proxy object can act as an intermediary between the client and the target object.

The Proxy constructor provided in ES6 makes it easy to use the Proxy pattern:

var proxy = new Proxy(target, handler);

Target The target object (which can be any type of object, including a native array, a function, or even another Proxy) to be wrapped with a Proxy.

Handler An object, usually with functions as attributes, that define the behavior of agent P when performing various operations.

// Simple implementation validation
let validator = {
  set: function(obj, prop, value) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError('The age is not an integer');
      }
      if (value > 200) {
        throw new RangeError('The age seems invalid'); }}// The default behavior to store the value
    obj[prop] = value;

    // Indicates success
    return true; }};let person = new Proxy({}, validator);
person.age = 100;
console.log(person.age);
/ / 100

person.age = 'young';
// Throw an exception: Uncaught TypeError: The age is not an INTEGER
person.age = 300;
// Throw an exception: Uncaught RangeError: The age seems invalid
Copy the code