webentwicklung-frage-antwort-db.com.de

JavaScript-Entwurfsmuster: Unterschied zwischen Modulmuster und aufdeckendem Modulmuster?

Ich lese gerade das Buch Learning JavaScript Design Patterns kürzlich. Was ich nicht verstehe, ist der Unterschied zwischen dem Modulmuster und dem aufdeckenden Modulmuster. Ich habe das Gefühl, dass sie dasselbe sind. Jeder kann ein Beispiel geben?

52
Wayou

Es gibt mindestens drei Möglichkeiten, das Modulmuster zu implementieren, aber das aufschlussreiche Modulmuster ist der einzige Nachkomme, der einen offiziellen Namen hat.

Das Basismodulmuster

Das Modulmuster muss Folgendes erfüllen:

  • Private Mitglieder leben in der Schließung.
  • Öffentliche Mitglieder werden im Rückgabeobjekt angezeigt.

In dieser Definition gibt es jedoch viel Zweideutigkeit. Durch die unterschiedliche Auflösung der Mehrdeutigkeit erhalten Sie Varianten des Modulmusters.

Das aufschlussreiche Modulmuster

Das aufschlussreiche Modulmuster ist die bekannteste und beliebteste der Modulmustervarianten. Es hat eine Reihe von Vorteilen gegenüber den anderen Alternativen, wie z

  • Benennen Sie öffentliche Funktionen um, ohne den Funktionskörper zu ändern.
  • Ändern Sie Mitglieder von öffentlich zu privat oder umgekehrt, indem Sie eine einzelne Zeile ändern, ohne den Funktionskörper zu ändern.

Der RMP erfüllt drei zusätzliche Bedingungen zusätzlich zu denen des Originals:

  • Alle Mitglieder, ob öffentlich oder privat, werden in der Schließung definiert.
  • Das zurückgegebene Objekt ist ein Objektliteral ohne Funktionsdefinitionen. Alle Ausdrücke auf der rechten Seite sind Schließvariablen
  • Alle Referenzen erfolgen über die Abschlussvariablen, nicht das Rückgabeobjekt.

Das folgende Beispiel zeigt, wie es verwendet wird

var welcomeModule = (function(){
  var name = "John";
  var hello = function(){ console.log("Hello, " + name + "!");}
  var welcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
  return {
    name: name,
    sayHello: hello,
    sayWelcome: welcome
  }
})();

Wenn Sie name und sayHello als privat definieren möchten, müssen Sie nur die entsprechenden Zeilen im Rückgabeobjekt auskommentieren.

var welcomeModule = (function(){
  var name = "John";
  var hello = function(){ console.log("Hello, " + name + "!");}
  var welcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
  return {
    //name: name,
    //sayHello: hello,
    sayWelcome: welcome
  }
})();

Das Modulmuster mit Objektliteral

Dies ist wahrscheinlich die älteste Variante des Modulmusters. Im Gegensatz zu RMP gibt es für diese Variante keinen offiziellen Namen. 

Es erfüllt zusätzlich zum Original folgende Bedingungen:

  • Private Mitglieder werden in der Schließung definiert.
  • Öffentliche Mitglieder werden im Rückkehrobjektliteral definiert.
  • Verweise auf öffentliche Mitglieder erfolgen nach Möglichkeit über this.

Im folgenden Beispiel können Sie sehen, wie sich die Funktionsdefinitionen im Gegensatz zu RMP tatsächlich im Rückkehrobjekt-Literal befinden, und Verweise auf Member werden durch this qualifiziert.

var welcomeModule = (function(){
  return {
    name: "John",
    sayHello: function(){ console.log("Hello, " + this.name + "!");}
    sayWelcome: function() { console.log( this.hello() + " Welcome to StackOverflow!");}
  }
})();

Wenn Sie RMP nicht aktivieren, um name und sayHello als privat zu definieren, müssen auch die Verweise auf name und sayHello in den verschiedenen Funktions-Body-Definitionen geändert werden.

var welcomeModule = (function(){
  var name: "John";
  var sayHello = function(){ console.log("Hello, " + name + "!");};
  return {
    //name: "John",
    //sayHello: function(){ console.log("Hello, " + this.name + "!");}
    sayWelcome: function() { console.log( hello() + " Welcome to StackOverflow!");}
  }
})();

Das Modulmuster mit Rückgabestub

Diese Variante hat auch keinen offiziellen Namen.

Es erfüllt zusätzlich zum Original folgende Bedingungen:

  • Am Anfang wird ein leerer Return-Objektstub definiert.
  • Private Mitglieder werden in der Schließung definiert.
  • Öffentliche Mitglieder werden als Mitglieder des Stubs definiert
  • Verweise auf öffentliche Mitglieder erfolgen über das Stub-Objekt

In unserem alten Beispiel können Sie sehen, dass öffentliche Mitglieder direkt zum Stub-Objekt hinzugefügt werden.

var welcomeModule = (function(){
  var stub = {};
  stub.name = "John";
  stub.sayHello = function(){ console.log("Hello, " + stub.name + "!");}
  stub.sayWelcome = function() { console.log( stub.hello() + " Welcome to StackOverflow!");}
  return stub;
})();

Wenn Sie name und sayHello wie zuvor als privat definieren möchten, müssen die Verweise auf die nun privaten Mitglieder geändert werden.

var welcomeModule = (function(){
  var stub = {};
  var name = "John";
  var sayHello = function(){ console.log("Hello, " + name + "!");}

  stub.sayWelcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
  return stub;
})();

Zusammenfassung

Der Unterschied zwischen dem aufschlussreichen Modulmuster und den anderen Varianten des Modulmusters liegt hauptsächlich in der Art und Weise, wie auf öffentliche Mitglieder verwiesen wird. Daher ist RMP viel einfacher zu verwenden und zu modifizieren, was seine Popularität ausmacht. Diese Vorteile sind jedoch (meiner Meinung nach) mit hohen Kosten verbunden, auf die Addy Osmani in seinem Beitrag zum Revealing Module Pattern , anspielt. 

Ein Nachteil dieses Musters ist, dass wenn eine private Funktion auf eine öffentliche Funktion verweist, diese öffentliche Funktion nicht überschrieben werden kann, wenn ein Patch erforderlich ist. Dies liegt daran, dass sich die private Funktion weiterhin auf die private Implementierung bezieht, und das Muster gilt nicht für öffentliche Mitglieder, sondern nur für Funktionen.

Öffentliche Objektmitglieder, die auf private Variablen verweisen, unterliegen ebenfalls den oben genannten No-Patch-Regelhinweisen.

Infolgedessen sind Module, die mit dem Muster "Entdeckungsmodul" erstellt wurden, möglicherweise anfälliger als diejenigen, die mit dem ursprünglichen Modulmuster erstellt wurden. Daher ist bei der Verwendung Vorsicht geboten.

und worüber ich in einigen anderenBeiträgen gesprochen habe.

98
I-Lin Kuo

Kurze Antwort, Im Modulmuster definieren wir Funktionen im zurückkehrenden Objekt.

Im Mustermodell "Aufdecken" definieren wir Funktionen im Schließbereich und verwenden nur Variablennamen in zurückgegebenen Objekten.

Dies vereinfacht den Code und bietet viele weitere Vorteile

1
Sumer

Versuchen Sie einfach etwas zu tun, basierend auf der Antwort der Antworten. Es ist möglicherweise sicherer, wenn eine private Funktion aufgerufen wird, indem this an sie übergeben wird, sodass die private Funktion auf die öffentliche Funktion mit der Variablen this verweisen kann.

Ich habe ein aufschlussreiches Modulmuster mit folgendem Code erstellt.

var HTMLChanger = (function () {
    var privateFunc = function () {
        this.sayHello();
    }

    var hello = function () {
        console.log('say Hello');
    }
    var callPrivate = function () {
        privateFunc.call(this);
    }


    return {
        sayHello: hello,
        callPrivate: callPrivate
    };
})();

HTMLChanger.callPrivate();
//say Hello

HTMLChanger.sayHello = function() { console.log('say Hi!') };

HTMLChanger.callPrivate();
//say Hi!

Wie Sie sehen, können wir öffentliche Mitglieder außer Kraft setzen.

0
Semooze