Sök…


Introduktion

Designmönster är ett bra sätt att hålla din kod läsbar och torka. Torkar står för inte upprepa dig själv . Nedan kan du hitta fler exempel på de viktigaste designmönstren.

Anmärkningar

Inom mjukvaruteknik är ett mönster för mjukvarudesign en allmän återanvändbar lösning på ett vanligt förekommande problem inom ett givet sammanhang inom mjukvarudesign.

Singletonmönster

Singleton-mönstret är ett designmönster som begränsar inställningen av en klass till ett objekt. När det första objektet har skapats, kommer det att returnera referensen till samma när det krävs ett objekt.

var Singleton = (function () {
        // instance stores a reference to the Singleton
        var instance;
    
        function createInstance() {
            // private variables and methods
            var _privateVariable = 'I am a private variable';
            function _privateMethod() {
                console.log('I am a private method');
            }

            return {
                // public methods and variables
                publicMethod: function() {
                    console.log('I am a public method');
                },
                publicVariable: 'I am a public variable'
            };
        }
         
        return {
            // Get the Singleton instance if it exists
            // or create one if doesn't
            getInstance: function () {
                if (!instance) {
                    instance = createInstance();
                }
                return instance;
            }
        };
    })();

Användande:

// there is no existing instance of Singleton, so it will create one
var instance1 = Singleton.getInstance();
// there is an instance of Singleton, so it will return the reference to this one
var instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true

Modul och avslöjande modulmönster

Modulmönster

Modulmönstret är ett kreativt och strukturellt designmönster som ger ett sätt att kapsla in privata medlemmar medan de producerar ett offentligt API. Detta åstadkoms genom att skapa en IIFE som tillåter oss att definiera variabler som endast är tillgängliga inom dess omfattning (genom stängning ) medan vi returnerar ett objekt som innehåller det offentliga API: et.

Detta ger oss en ren lösning för att dölja huvudlogiken och bara avslöja ett gränssnitt som vi önskar att andra delar av vår applikation ska använda.

var Module = (function(/* pass initialization data if necessary */) {
  // Private data is stored within the closure
  var privateData = 1;

  // Because the function is immediately invoked,
  // the return value becomes the public API
  var api = {
    getPrivateData: function() {
      return privateData;
    },
    
    getDoublePrivateData: function() {
      return api.getPrivateData() * 2;
    }
  };
  return api;
})(/* pass initialization data if necessary */);

Avslöjande modulmönster

Det avslöjande modulmönstret är en variant i modulmönstret. De viktigaste skillnaderna är att alla medlemmar (privata och offentliga) definieras inom stängningen, returvärdet är ett bokstavligt objekt som inte innehåller några funktionsdefinitioner, och alla referenser till medlemsdata görs genom direkta referenser snarare än genom det returnerade objektet.

var Module = (function(/* pass initialization data if necessary */) {
  // Private data is stored just like before
  var privateData = 1;

  // All functions must be declared outside of the returned object
  var getPrivateData = function() {
    return privateData;
  };

  var getDoublePrivateData = function() {
    // Refer directly to enclosed members rather than through the returned object
    return getPrivateData() * 2;
  };

  // Return an object literal with no function definitions
  return {
    getPrivateData: getPrivateData,
    getDoublePrivateData: getDoublePrivateData
  };
})(/* pass initialization data if necessary */);

Avslöjande prototypmönster

Denna variation av det avslöjande mönstret används för att separera konstruktören till metoderna. Det här mönstret tillåter oss att använda javascript-språket som ett objektorienterat språk:

//Namespace setting
var NavigationNs = NavigationNs || {};

// This is used as a class constructor 
NavigationNs.active = function(current, length) {        
    this.current = current;
    this.length = length;
}

// The prototype is used to separate the construct and the methods    
NavigationNs.active.prototype = function() {
    // It is a example of a public method because is revealed in the return statement
    var setCurrent = function() {
        //Here the variables current and length are used as private class properties  
        for (var i = 0; i < this.length; i++) {                
                $(this.current).addClass('active');                 
        }
    }
    return { setCurrent: setCurrent };
}();

// Example of parameterless constructor  
NavigationNs.pagination = function() {}

NavigationNs.pagination.prototype = function() {
// It is a example of a private method because is not revealed in the return statement
    var reload = function(data) {
        // do something
    },
    // It the only public method, because it the only function referenced in the return statement
     getPage = function(link) {
        var a = $(link);

        var options = {url: a.attr('href'), type: 'get'}
        $.ajax(options).done(function(data) {            
           // after the the ajax call is done, it calls private method
           reload(data);
        });

        return false;
    }
    return {getPage : getPage}
}();

Den här koden ovan bör finnas i en separat fil .js som ska refereras till på vilken sida som behövs. Det kan användas så här:

var menuActive = new NavigationNs.active('ul.sidebar-menu li', 5);
menuActive.setCurrent();

Prototypmönster

Prototypmönstret fokuserar på att skapa ett objekt som kan användas som en plan för andra objekt genom prototyparv. Det här mönstret är i sig naturligt lätt att arbeta med i JavaScript på grund av det ursprungliga stödet för prototypformad arv i JS vilket innebär att vi inte behöver spendera tid eller ansträngningar för att imitera denna topologi.


Skapa metoder på prototypen

function Welcome(name) {
  this.name = name;
}
Welcome.prototype.sayHello = function() {
  return 'Hello, ' + this.name + '!';
}

var welcome = new Welcome('John');

welcome.sayHello();
// => Hello, John!

Prototypisk ärft

Arv från ett "föräldraobjekt" är relativt enkelt via följande mönster

ChildObject.prototype = Object.create(ParentObject.prototype);
ChildObject.prototype.constructor = ChildObject;

Där ParentObject är det objekt du vill ärva de prototypade funktionerna från, och ChildObject är det nya objektet du vill sätta dem på.

Om förälderobjektet har värden som det initialiseras i sin konstruktör måste du ringa föräldrakonstruktören när du initialiserar barnet.

Du gör det med följande mönster i ChildObject konstruktören.

function ChildObject(value) {
    ParentObject.call(this, value);
}

Ett komplett exempel där ovanstående implementeras

function RoomService(name, order) {
  // this.name will be set and made available on the scope of this function
  Welcome.call(this, name);
  this.order = order;
}

// Inherit 'sayHello()' methods from 'Welcome' prototype
RoomService.prototype = Object.create(Welcome.prototype);

// By default prototype object has 'constructor' property. 
// But as we created new object without this property  -  we have to set it manually,
// otherwise 'constructor' property will point to 'Welcome' class
RoomService.prototype.constructor = RoomService;

RoomService.prototype.announceDelivery = function() {
  return 'Your ' + this.order + ' has arrived!';
}
RoomService.prototype.deliverOrder = function() {
  return this.sayHello() + ' ' + this.announceDelivery();
}

var delivery = new RoomService('John', 'pizza');

delivery.sayHello();
// => Hello, John!,

delivery.announceDelivery();
// Your pizza has arrived!

delivery.deliverOrder();
// => Hello, John! Your pizza has arrived!

Fabriksfunktioner

En fabriksfunktion är helt enkelt en funktion som returnerar ett objekt.

Fabriksfunktioner kräver inte användning av det new nyckelordet, men kan fortfarande användas för att initialisera ett objekt, som en konstruktör.

Ofta används fabriksfunktioner som API-omslag, som i fallet med jQuery och moment.js , så användarna behöver inte använda new .

Följande är den enklaste formen av fabriksfunktion; ta argument och använda dem för att skapa ett nytt objekt med objektet bokstavligt:

function cowFactory(name) {
    return {
        name: name,
        talk: function () {
            console.log('Moo, my name is ' + this.name);
        },
    };
}

var daisy = cowFactory('Daisy');  // create a cow named Daisy
daisy.talk();  // "Moo, my name is Daisy"

Det är lätt att definiera privata egenskaper och metoder i en fabrik genom att inkludera dem utanför det returnerade objektet. Detta håller dina implementeringsdetaljer inkapslade, så att du bara kan exponera det offentliga gränssnittet för ditt objekt.

function cowFactory(name) {
    function formalName() {
        return name + ' the cow';
    }

    return {
        talk: function () {
            console.log('Moo, my name is ' + formalName());
        },
    };
}

var daisy = cowFactory('Daisy');
daisy.talk();  // "Moo, my name is Daisy the cow"
daisy.formalName();  // ERROR: daisy.formalName is not a function

Den sista raden kommer att ge ett fel eftersom funktionsformellt formalName är stängt i cowFactory funktionen. Detta är en stängning .

Fabriker är också ett bra sätt att tillämpa funktionella programmeringsmetoder i JavaScript, eftersom de är funktioner.

Fabrik med komposition

"Föredrar komposition framför arv" är en viktig och populär programmeringsprincip som används för att tilldela beteenden till objekt, i motsats till att ärva många ofta onödiga beteenden.

Beteende fabriker

var speaker = function (state) {
    var noise = state.noise || 'grunt';

    return {
        speak: function () {
            console.log(state.name + ' says ' + noise);
        }
    };
};

var mover = function (state) {
    return {
        moveSlowly: function () {
            console.log(state.name + ' is moving slowly');
        },
        moveQuickly: function () {
            console.log(state.name + ' is moving quickly');
        }
    };
};

Objektfabriker

6
var person = function (name, age) {
    var state = {
        name: name,
        age: age,
        noise: 'Hello'
    };

    return Object.assign(     // Merge our 'behaviour' objects
        {},
        speaker(state),
        mover(state)
    );
};

var rabbit = function (name, colour) {
    var state = {
        name: name,
        colour: colour
    };

    return Object.assign(
        {},
        mover(state)
    );
};

Användande

var fred = person('Fred', 42);
fred.speak();        // outputs: Fred says Hello
fred.moveSlowly();   // outputs: Fred is moving slowly

var snowy = rabbit('Snowy', 'white');
snowy.moveSlowly();  // outputs: Snowy is moving slowly
snowy.moveQuickly(); // outputs: Snowy is moving quickly
snowy.speak();       // ERROR: snowy.speak is not a function

Abstrakt fabriksmönster

Det abstrakta fabriksmönstret är ett kreativt designmönster som kan användas för att definiera specifika instanser eller klasser utan att behöva ange det exakta objektet som skapas.

function Car() { this.name = "Car"; this.wheels = 4; }
function Truck() { this.name = "Truck"; this.wheels = 6; }
function Bike() { this.name = "Bike"; this.wheels = 2; }

const vehicleFactory = {
    createVehicle: function (type) {
        switch (type.toLowerCase()) {
            case "car":
                return new Car();
            case "truck":
                return new Truck();
            case "bike":
                return new Bike();
            default:
                return null;
        }
    }
};

const car = vehicleFactory.createVehicle("Car"); // Car { name: "Car", wheels: 4 }  
const truck = vehicleFactory.createVehicle("Truck"); // Truck { name: "Truck", wheels: 6 }  
const bike = vehicleFactory.createVehicle("Bike"); // Bike { name: "Bike", wheels: 2 }  
const unknown = vehicleFactory.createVehicle("Boat"); // null ( Vehicle not known )


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow