Recherche…


Introduction

Les modèles de conception sont un bon moyen de garder votre code lisible et SEC. DRY signifie ne pas répéter vous-même . Vous trouverez ci-dessous d'autres exemples de modèles de conception les plus importants.

Remarques

En génie logiciel, un modèle de conception de logiciel est une solution généralement réutilisable à un problème courant dans un contexte donné lors de la conception de logiciels.

Motif Singleton

Le modèle Singleton est un modèle de conception qui limite l'instanciation d'une classe à un objet. Une fois le premier objet créé, il renverra la référence au même chaque fois qu’il sera appelé pour un objet.

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;
            }
        };
    })();

Usage:

// 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

Modules de module et de module révélateur

Modèle de module

Le modèle de module est un modèle de conception créative et structurelle qui permet d'encapsuler des membres privés tout en produisant une API publique. Ceci est accompli en créant un IIFE qui nous permet de définir des variables uniquement disponibles dans sa portée (via la fermeture ) tout en retournant un objet qui contient l’API publique.

Cela nous donne une solution propre pour cacher la logique principale et exposer uniquement une interface que nous souhaitons que d’autres parties de notre application utilisent.

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 */);

Modèle de module révélateur

Le modèle de module révélateur est une variante du modèle de module. Les principales différences sont que tous les membres (privés et publics) sont définis dans la fermeture, la valeur de retour est un littéral d'objet ne contenant aucune définition de fonction et toutes les références aux données membres sont effectuées via des références directes plutôt que par l'objet renvoyé.

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 */);

Motif de prototype révélateur

Cette variation du motif révélateur est utilisée pour séparer le constructeur des méthodes. Ce modèle nous permet d'utiliser le langage javascript comme un langage orienté objet:

//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}
}();

Ce code ci-dessus doit être dans un fichier séparé .js à référencer dans n'importe quelle page nécessaire. Il peut être utilisé comme ceci:

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

Motif Prototype

Le modèle de prototype se concentre sur la création d'un objet pouvant être utilisé comme modèle pour d'autres objets via l'héritage de prototypes. Ce modèle est intrinsèquement facile à utiliser en JavaScript en raison de la prise en charge native de l'héritage prototype dans JS, ce qui signifie que nous n'avons pas besoin de consacrer du temps ou des efforts à l'imitation de cette topologie.


Créer des méthodes sur le prototype

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

var welcome = new Welcome('John');

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

Héritage prototypique

L'héritage d'un «objet parent» est relativement facile via le schéma suivant

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

ParentObject est l'objet à partir ParentObject vous souhaitez hériter des fonctions prototypées, et ChildObject est le nouvel objet sur ChildObject vous souhaitez les placer.

Si l'objet parent a des valeurs qu'il initialise dans son constructeur, vous devez appeler le constructeur parent lors de l'initialisation de l'enfant.

Vous faites cela en utilisant le modèle suivant dans le constructeur ChildObject .

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

Un exemple complet où ce qui précède est mis en œuvre

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!

Fonctions d'usine

Une fonction usine est simplement une fonction qui renvoie un objet.

Les fonctions d'usine ne nécessitent pas l'utilisation du mot-clé new , mais peuvent toujours être utilisées pour initialiser un objet, comme un constructeur.

Souvent, les fonctions d'usine sont utilisées comme wrappers API, comme dans le cas de jQuery et moment.js , de sorte que les utilisateurs n'ont pas besoin d'utiliser new .

Ce qui suit est la forme la plus simple de la fonction d'usine; prendre des arguments et les utiliser pour créer un nouvel objet avec le littéral objet:

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"

Il est facile de définir des propriétés et des méthodes privées dans une fabrique, en les incluant en dehors de l'objet renvoyé. Cela conserve vos détails d'implémentation encapsulés, de sorte que vous ne pouvez exposer que l'interface publique à votre objet.

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

La dernière ligne donnera une erreur car la fonction formalName est fermée dans la fonction cowFactory . Ceci est une fermeture .

Les usines sont également un excellent moyen d'appliquer des pratiques de programmation fonctionnelle en JavaScript, car ce sont des fonctions.

Usine avec Composition

«Préférer la composition à l'héritage» est un principe de programmation important et populaire, utilisé pour attribuer des comportements aux objets, au lieu d'hériter de nombreux comportements souvent inutiles.

Usines de comportement

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');
        }
    };
};

Usines d'objets

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)
    );
};

Usage

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

Motif d'usine abstraite

Le motif de fabrique abstrait est un motif de conception créative qui peut être utilisé pour définir des instances ou des classes spécifiques sans avoir à spécifier l'objet exact en cours de création.

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow