Beispiele für praktische objektorientierte Javascript-Entwurfsmuster

81

Welche objektorientierten Entwurfsmuster verwenden Sie im Javascript Ihrer Anwendung und warum?

Sie können gerne eine Postleitzahl eingeben, auch wenn kein formales Entwurfsmuster beigefügt ist.

Ich habe viel Javascript geschrieben, aber ich habe nicht viele objektorientierte Muster auf das angewendet, was ich tue, und ich bin sicher, dass mir viel fehlt.

ming yeow
quelle
Sie haben die klassische OOP wahrscheinlich nicht in dem Sinne gesehen, wie Sie vielleicht denken. Wahrscheinlich haben Sie jedoch Funktionen mit prototypischem OOP verwendet und dies nie wirklich realisiert.
Dave
Ich mache eigentlich (manchmal) erkennen , wenn ich OOP bin mit - ich will bewusst viel mehr mit OOP starten, gerade weil ich es viel mehr überlegen sein wollen
ming yeow
Ich stimme dafür, diese Frage als nicht zum Thema gehörend zu schließen, weil sie nur nach einer Liste von Dingen fragt, die andere Leute in ihrem Code tun.
Almo

Antworten:

54

Im Folgenden sind drei beliebte JavaScript-Muster aufgeführt. Diese sind aufgrund von Schließungen leicht zu implementieren :

Vielleicht möchten Sie auch Folgendes überprüfen:

Das Folgende ist ein Google I / O-Vortrag aus dem Jahr 2008, der von Diaz präsentiert wird und in dem er einige Themen aus seinem Buch behandelt:

Daniel Vassallo
quelle
nett! Curry sieht nach einer viel intelligenteren Methode aus, um einige der Verallgemeinerungen zu machen, die ich versucht habe. Ich verwende bereits einfache Formen von Modulen und Memoisierung - aber ich muss diese Beispiele studieren, um zu zeigen, wie ich es derzeit mache. Welche benutzt du am meisten?
Ming yeow
@ming: Wahrscheinlich ist es das Modulmuster. Sehr einfach zu implementieren und zu verstehen, und es kommt mit einigen coolen Funktionen, einschließlich Namespace und privaten Variablen / Methoden.
Daniel Vassallo
26

Erbe

Ich verwende eine Notation für die Vererbung , die auf ExtJS 3 basiert. Ich finde, dass dies der Emulation der klassischen Vererbung in Java ziemlich nahe kommt. Es läuft grundsätzlich wie folgt ab:

// Create an 'Animal' class by extending
// the 'Object' class with our magic method
var Animal = Object.extend(Object, {
    move : function() {alert('moving...');}
});

// Create a 'Dog' class that extends 'Animal'
var Dog = Object.extend(Animal, {
    bark : function() {alert('woof');}
});

// Instantiate Lassie
var lassie = new Dog();

// She can move and bark!
lassie.move();
lassie.bark();

Namespaces

Ich stimme auch Eric Miraglia darin zu, sich an Namespaces zu halten, sodass der obige Code in einem eigenen Kontext außerhalb des Fensterobjekts ausgeführt werden sollte. Dies ist wichtig, wenn Sie beabsichtigen, Ihren Code als eines von vielen gleichzeitigen Frameworks / Bibliotheken auszuführen, die im Browserfenster ausgeführt werden.

Dies bedeutet, dass der einzige Weg zum Fensterobjekt über Ihren eigenen Namespace / Modulobjekt führt:

// Create a namespace / module for your project
window.MyModule = {};

// Commence scope to prevent littering 
// the window object with unwanted variables
(function() {

    var Animal = window.MyModule.Animal = Object.extend(Object, {
         move: function() {alert('moving...');}
    });

    // .. more code

})();

Schnittstellen

Sie können auch fortschrittlichere OOP-Konstrukte wie Schnittstellen verwenden, um Ihr Anwendungsdesign zu verbessern. Mein Ansatz bei diesen ist es, die zu verbessern Function.prototype, um eine Notation in dieser Richtung zu erhalten:

var Dog = Object.extend(Animal, {
     bark: function() {
         alert('woof');
     }
     // more methods ..
}).implement(Mammal, Carnivore);

OO-Muster

Was 'Patterns' im Java-Sinne betrifft, habe ich nur Verwendung für das Singleton-Pattern (ideal zum Zwischenspeichern) und das Observer-Pattern gefunden für ereignisgesteuerte Funktionen gefunden, z. B. das Zuweisen einiger Aktionen, wenn ein Benutzer auf eine Schaltfläche klickt.

Ein Beispiel für die Verwendung des Beobachtermusters wäre:

// Instantiate object
var lassie = new Animal('Lassie');

// Register listener
lassie.on('eat', function(food) {
   this.food += food;
});

// Feed lassie by triggering listener
$('#feeding-button').click(function() {
    var food = prompt('How many food units should we give lassie?');
    lassie.trigger('eat', [food]);
    alert('Lassie has already eaten ' + lassie.food + ' units');
});

Und das sind nur ein paar Tricks in meiner Tasche von OO JS, ich hoffe, sie sind nützlich für Sie.

Ich empfehle, wenn Sie diesen Weg gehen möchten, Douglas Crockfords Javascript: the Good Parts zu lesen . Es ist ein brillantes Buch für dieses Zeug.

Steven de Salas
quelle
20

Ich bin ein Fan des Modulmusters . Dies ist eine Möglichkeit, erweiterbare, nicht abhängige (meistens) Frameworks zu implementieren.

Beispiel:

Das Framework Qist wie folgt definiert:

var Q = {};

So fügen Sie eine Funktion hinzu:

Q.test = function(){};

Diese beiden Codezeilen werden zusammen verwendet, um Module zu bilden . Die Idee hinter Modulen ist, dass sie alle in diesem Fall ein Basis-Framework erweitern Q, aber nicht voneinander abhängig sind (wenn sie richtig entworfen wurden) und in beliebiger Reihenfolge enthalten sein können.

In einem Modul erstellen Sie zuerst das Framework-Objekt, wenn es nicht vorhanden ist (ein Beispiel für das Singleton- Muster):

if (!Q)
    var Q = {};

Q.myFunction = function(){};

Auf diese Weise können Sie mehrere Module (wie das obige) in separaten Dateien haben und diese in beliebiger Reihenfolge einfügen. Jeder von ihnen erstellt das Framework-Objekt und erweitert es dann. Es muss kein Handbuch überprüft werden, ob das Framework vorhanden ist. So überprüfen Sie, ob ein Modul / eine Funktion im benutzerdefinierten Code vorhanden ist:

if (Q.myFunction)
    Q.myFunction();
else
    // Use a different approach/method
Chris Laplante
quelle
1
Das sieht sehr nützlich aus. Wie verwenden Sie dies in Ihrem Code? danke für das Teilen!
Ming yeow
Ich habe es kürzlich in einem Projekt verwendet, in dem ich separate JavaScript-Dateien für die allgemeinen Funktionen, die Benutzeroberfläche und zwei andere spezialisierte Mechanismen hatte. Alle Dateien fügten Funktionen demselben Framework hinzu (definiert mit der oben gezeigten Methode) und riefen die Funktionen wie oben beschrieben auf.
Chris Laplante
Eine der Hauptanwendungen für diese Art von Technik ist die Vermeidung einer Verschmutzung des globalen Namespace. Was verschmutzt mehr? Eine einzelne QFramework-Variable oder Dutzende und Dutzende von Funktionen und Variablen?
Chris Laplante
6

Das Singleton-Muster ist oft sehr hilfreich für die Kapselung und Organisation. Sie können sogar die Zugänglichkeit ändern.

var myInstance = {
  method1: function () {
    // ...
  },
  method2: function () {
    // ...
  }
};

sauberste Möglichkeit, einen Singleton in Javascript zu implementieren

Gordon Gustafson
quelle
genial - Dies ist die, die ich die ganze Zeit benutze! Aber das ist ungefähr das Ausmaß meines Javascript OO. ;)
ming yeow
4

Ich mag das Methodenverkettungsmuster von jquery sehr , mit dem Sie mehrere Methoden für ein Objekt aufrufen können. Es macht es wirklich einfach, mehrere Operationen in einer einzigen Codezeile auszuführen.

Beispiel:

$('#nav').click(function() {
   $(this).css('color','#f00').fadeOut();
});
GSto
quelle
richtig - vereinbart! Haben Sie schon einmal eigene Methoden entwickelt, die so funktionieren?
Ming Yeow
3

Ich mag das Decorator-Muster mit jQuery-Plugins sehr. Anstatt Plugins an Ihre Bedürfnisse anzupassen, schreiben Sie ein benutzerdefiniertes Plugin, das nur Anfragen weiterleitet und zusätzliche Parameter und Funktionen hinzufügt.

Wenn Sie beispielsweise ständig eine Reihe von Standardargumenten übergeben müssen und ein etwas anderes Verhalten benötigen, das mit der Geschäftslogik verknüpft ist, schreiben Sie ein Plugin, das alles tut preund funktioniert, was postIhren Anforderungen entspricht, und Ihre Standardargumente übergibt wenn diese speziellen Argumente nicht angegeben sind.

Der Hauptvorteil davon ist, dass Sie Ihre Bibliotheken aktualisieren können und sich nicht um das Portieren von Bibliotheksänderungen kümmern müssen. Ihr Code könnte kaputt gehen, aber es besteht zumindest die Möglichkeit, dass dies nicht der Fall ist.

Stefan Kendall
quelle
Das klingt nach einer großartigen Idee. Haben Sie ein aktuelles Beispiel für den Code, um die eigentliche Erweiterung durchzuführen? Selbst ein einfaches Beispiel wird allen sehr helfen.
Ming yeow
3

Eines der nützlichen Muster in der Javascript-Welt ist das Verkettungsmuster, das von LINQ an erster Stelle populär gemacht wird und auch in jQuery verwendet wird.

Dieses Muster ermöglicht es uns, verschiedene Methoden einer Klasse verkettet aufzurufen.

Die Hauptstruktur dieses Musters wäre wie folgt

var Calaculator = function (init) {
    var result = 0;
    this.add = function (x) { result += (init + x); return this; };
    this.sub = function (x) { result += (init - x); return this; };
    this.mul = function (x) { result += (init * x); return this; };
    this.div = function (x) { result += (init / x); return this; };

    this.equals = function (callback) {
        callback(result);
    }

    return this;
};


new Calaculator(0)
    .add(10)
    .mul(2)
    .sub(5)
    .div(3)
    .equals(function (result) {
        console.log(result);
    });

Die Schlüsselidee dieses Musters ist das thisSchlüsselwort, das den Zugriff auf andere öffentliche Mitglieder der Calculator-Funktion ermöglicht.

Matrix Buster
quelle