JavaScript Design Patterns

Keywords: Javascript Programming Fragment

1. Singleton Model

  • Definition: A specific class has only one instance

  • Application scenarios: A mask

  • Realization way

    1. Each object is a monomer, because their reference positions are different.

    2. Use the new operator

      • Store the first generated object in a global variable. Disadvantage: Global variables are easily overwritten. You can use closures to store this variable, see A mask.

      • Store the instance in the attributes of the constructor. Disadvantage: Constructor properties can also be easily modified.

        function Universe() {
            if (typeof Universe.instance === "object") {
                return Universe.instance
            }

            this.start_time = 0;
            this.bang = "Big";

            Universe.instance = this;
        }

        var uni1 = new Universe();
        var uni2 = new Universe();

        console.log(uni1 === uni2); // true    
    - Rewrite the constructor and use closures to store the instance. Disadvantages:
//Disadvantage: This approach discards the relationship between the initial instance and the override constructor, so later adding attributes to the override constructor prototype will not be added to the initial instance.
        function Universe() {
            var instance = this;
            this.start_time = 0;
            this.bang = "Big";

            Universe = function Universe() {
                return instance;
            }
        }

        Universe.prototype.nothing = true;
        var uni1 = new Universe();

        Universe.prototype.everything = true;
        var uni2 = new Universe();

        console.log(uni1 === uni2); //true
        console.log(uni1.nothing); //true
        console.log(uni2.nothing); //true
        console.log(uni1.everything); //undefined
        console.log(uni2.everything); //undefined    
        console.log(uni1.constructor === Universe); //false

Therefore, we need to rewrite the constructor first, preserve the prototype properties, generate instances, and return instances.

        function Universe() {
            var instance;
            
            Universe = function () {
                return instance;
            }

            Universe.prototype = this;

            instance = new Universe();
            instance.constructor = Universe;

            this.start_time = 0;
            this.bang = "big";

            return instance;
        }

        Universe.prototype.nothing = true;
        var uni1 = new Universe();

        Universe.prototype.everything = true;
        var uni2 = new Universe();

        console.log(uni1 === uni2); //true
        console.log(uni1.nothing); //true
        console.log(uni2.nothing); //true
        console.log(uni1.everything); //true
        console.log(uni2.everything); //true
        console.log(uni1.constructor === Universe); //true
- Another way is to use instant functions.
        var Universe;
        (function () {
            var instance;
            Universe =     function () {
                if (instance) {
                    return instance;
                }

                instance = this;
                this.start_time = 0;
                this.bang = "big";
            }
        })();

        Universe.prototype.nothing = true;
        var uni1 = new Universe();

        Universe.prototype.everything = true;
        var uni2 = new Universe();

        console.log(uni1 === uni2); //true
        console.log(uni1.nothing); //true
        console.log(uni2.nothing); //true
        console.log(uni1.everything); //true
        console.log(uni2.everything); //true
        console.log(uni1.constructor === Universe); //true    

2. Factory Model

  • Definition: Provides reusable methods for creating similar objects. In uncertain situations, provide a way to create a class in advance. Total-sub model.

  • Application Scenario: A CarMaker constructor that provides factory methods for creating different types of cars.

  • The way of realization. Advantages: Protect the global namespace from contamination and quickly find the corresponding constructor.

        function CarMaker() {}
        
        CarMaker.prototype.getPrice =     function () {
            console.log("Price:", this.price);
        }

        CarMaker.factory = function (type) {
            var newcar;
            //If the constructor does not exist, an error is reported
            if (typeof CarMaker[type] !== "function") {
                throw {
                    name: "Error",
                    message: type + " dosen't exist"
                }
            }

            //The prototype inherits the parent class only once
            if (typeof CarMaker[type].prototype.getPrice !== "function") {
                CarMaker[type].prototype = new CarMaker();
            }

            newcar = new CarMaker[type]();
            return newcar;
        }

        CarMaker.SUV = function () {
            this.price = 100;
        }

        CarMaker.Compat = function () {
            this.price = 50;
        }

        var a = CarMaker.factory("SUV");
        var b = CarMaker.factory("Compat");

        a.getPrice(); //Price: 100
        b.getPrice(); //Price: 100

3. Iterator pattern

  • Definition: Access elements of an aggregated object sequentially. Usually includes next (get the next element), hasNext (whether to the end), rewind (reset the initial position), and current (current element) centralization methods.

  • Application scenarios: The elements in the collection need to be retrieved at different intervals in order.

  • Method of realization:

function iterator (data = [], gap = 1) {
         var index = 0, //Record the current location
                 length = data.length; //Total length of data
         return {
             next() {
                 var element;
                 if (!this.hasNext()) {
                     return null;
                 }
                 element = data[index];
                 index += gap;
                 return element;
             },
             hasNext() {
                 return index < length;
             },
             rewind() {
                 index = 0;
             },
             current() {
                 return data[index];
             }
         }
     }

     var arrIterator = iterator([1, 2, 3, 4, 5]);

     while(arrIterator.hasNext()) {
         console.log(arrIterator.next());
     }

     arrIterator.rewind();
     console.log(arrIterator.current());

4. Decorator Model

  • Definition: Dynamic addition of additional functions to objects at runtime.

  • Application scenario: When buying something, the price varies with the addition of different equipment. Finally, we need to calculate the total price according to the added equipment.

  • Implementing method: It should be noted that each decorator needs to provide the interface of the prototype method. Another way of implementation

        function Sale(price = 100) {
            this.price = price;
            this.decorators_list = [];
        }

        //Decorator
        Sale.decorators = {};
        Sale.decorators.pack = {
            getPrice(price) {
                return price + 20;
            }
        }
        Sale.decorators.mail = {
            getPrice(price) {
                return price + 10;
            }
        }

        Sale.prototype.decorate = function (decorator) {
            this.decorators_list.push(decorator);
        }

        Sale.prototype.getPrice = function () {
            let price = this.price;
            //Call the interface of each decorator
            for (let i = 0, len = this.decorators_list.length; i < len; i++) {
                name = this.decorators_list[i];
                price = Sale.decorators[name].getPrice(price);
            }
            return price;
        }

        var sale = new Sale();
        sale.decorate('pack');
        sale.decorate('mail');
        console.log(sale.getPrice()); //130

5. Strategist Model

  • Definition: Algorithms can be selected at runtime.

  • Application scenario: Form validation.

  • Implementation: A validator object with several attributes of config, types, validate, message and hasErrors.

6. Appearance pattern

  • Definition: Provide a high-level interface to invoke several basic methods that are often used at the same time.

  • Application scenario: Pack stop Propagation and peventDefault in the advanced interface of stop.

The cooker in the dining hall won't cook the two dishes in a pot just because you ordered a roast duck and a cabbage. He prefers to offer you a roast duck meal set. Similarly, in programming, we need to ensure that functions or objects are as granular as possible. After all, not everyone likes roast duck while eating cabbage.

Another advantage of appearance mode is that it can hide the real implementation details from users, who only care about the top-level interface. For example, in the story of the roast duck meal set, you don't care whether the master cooks roast duck or fried cabbage first, nor do you care where the duck grew up.

7. Agency Model

  • Definition: Between the object and the object's client, it protects the object's ontology and makes the ontology object do as little work as possible. The goal is to solve performance problems.

  • Application scenarios:

    • Initialization of ontology objects is expensive, but it is not used after initialization. At this time, we can use proxy mode, receive initialization requests, return ok, and then initialize when the ontology object is really used.

    • Initiating Http requests consumes performance, and the best way is to merge Http requests using proxies, such as merging the originated requests within 50ms into one request.

    • In order to reduce performance consumption, a cache can also be set up for the proxy to cache the results.

    • fragment should be a proxy mode, caching operations on DOM.

  • Implementing method: The object client calls the method provided by the proxy, and the proxy calls the object ontology method after processing the client's request.

8. Intermediary Model

  • Definition: There are many objects in a program that communicate with each other. But if one of the objects is modified, it will inevitably involve other objects communicating with him, resulting in tight coupling. The mediator pattern is to propose an intermediate object to realize loosely coupled communication between objects. The communicating object does not need to know who the other party is. As long as there is a change, the intermediary notifies the intermediary. The intermediary knows all the objects and is responsible for contacting the corresponding objects for processing.

  • Application scenario: Controller in MVC

  • Method of realization: http://www.jspatterns.com/boo...

9. Observer model

  • Definition: The purpose of this model is also to form loose coupling. Objects do not call each other's methods directly, but adopt the subscription mode. Subscribers subscribe to publisher's events and provide publishers with a method to call when an event occurs. The mediator in the mediator pattern needs to know all other objects, and the mediator pattern does not need to know, just subscribe to events.

  • Application scenario: Events in DOM.

  • Method of realization:
    Publisher needs: list of subscribers {type: []}, subscription methods, unsubscribe, and several methods of publishing messages. http://www.jspatterns.com/boo...

Posted by tcr480 on Tue, 16 Apr 2019 17:27:32 -0700