2017-12-18 2 views
7

angegeben Ich habe eine Klassenhierarchie wie:Node.js - erstellen Objekt des Klassennamen in den Variablen

   |-> Square 
AbstractShape -+-> Circle 
       |-> Triangle 

Nun, würde Ich mag Strategie-Muster implementieren und ein Objekt der Klasse erstellen, die in einem String gespeichert sind. In PHP würde ich verwenden:

$type = 'Square'; 
$obj = new $type(); 

Gibt es eine Entsprechung in Node.js?

+0

Es ist wie das Aufrufen von 'new Square()' – zabusa

Antwort

4

Wenn Sie wollen, mit einem robusteren und prüfbar Ansatz gehen, könnten Sie Verwenden Sie eine Kombination aus Klassen und einem Fabrikmuster, um das Objekt auszugeben. Sehen Sie sich Folgendes an, Sie werden sehen, dass mit dieser Konfiguration, einschließlich einer detaillierteren Logik und Tests auf der Straße, einfacher wird und Ihnen eine größere Flexibilität bietet. Sie abstrahieren auch weg das Objekt selbst hinter dem .issue Anruf neu - was in einigen Fällen vorteilhaft und bequem sein kann.

Ich merke auch, dass Sie Ihren PHP-Hintergrund erwähnen, also zeige ich auch ein bisschen, wie ein objektorientierter Ansatz in ES6 genommen werden kann.

class AbstractShape { 
    constructor(type) { 
    this.type = type; 
    } 

    getType() { 
    console.log(`I am a ${this.type}`); 
    } 
} 

class Square extends AbstractShape { 
    constructor(type) { 
    super(type); 
    this.sides = 4; 
    } 

    getDescription() { 
    console.log(`I have ${this.sides} equal sides`); 
    } 
} 

class ShapeFactory { 
    static issue(type) { 
    switch(type) { 
     case 'Square': return new Square(type); 
     break; 
     case 'Circle': /* same pattern with a Circle class */ 
     break; 
    } 
    } 
} 

let shape = ShapeFactory.issue('Square'); 

shape.getType();  /* I am a Square */ 
shape.getDescription(); /* I have 4 equal sides */ 

JSFiddle Link - Demo


Des Weiteren würden, wenn Sie etwas ein bisschen mehr fehlertolerant als den Umgang mit redundanten Strings wie zum Beispiel 'Square' - there are some creative ways um Enum-ähnliche Ansätze zu nutzen, die dies noch weiter verfeinern könnten. Ich werde die Immobilien hier speichern und das Code-Snippet nicht erneut hashen, sondern werde eine Geige für Sie einschließen.

JSFiddle Link - Enum Ansatz Demo

2
  1. Der schnelle und schmutzige Weg ist die Verwendung eval. Aber es ist stark nicht aus vielen Gründen empfohlen - Sicherheit, Leistung, Lesbarkeit, Wartbarkeit

    function MyType() { 
    } 
    
    var typeName = 'MyType'; 
    var typeObj = eval('new ' + typeName + '()'); 
    
  2. Viele sicherer und richtiger als eval Abbildung von String-Namen zu verwenden ist, um Typen (dank @GaloisGecko)

    function createType(name) { 
        var types = { 
        "Square": Square, 
        "Circle": Circle, 
        "Triangle": Tringle 
        }; 
        return types.hasOwnProperty(name) ? new types[name]() : null; 
    } 
    
  3. Schließlich ist die beste und weise Entscheidung, Fabrikmuster anzuwenden. Siehe @scniro answer. Sie können auch eine gute Beschreibung und ein Beispiel here

+0

Wann immer möglich 'eval' nicht verwenden. Und hier musst du nicht, also halte dich von dieser Lösung fern. –

4

Ein sicherer Weg, eine Fabrik finden Objekt würde definieren:

function Square() { 
} 

// here other constructors for Circle and Triangle 

var factory = { 
    "Square": Square, 
    "Circle": Circle, 
    "Triangle" : Triangle 
} 

var typeName; 

// here some code which sets typeName 

var typeObj = new factory[typeName](); 
1

Bei näherer Betrachtung gibt es ganz einfache Art und Weise um für Node.js. Wenn Sie ein Objekt auf einfachste Weise instanziieren, schreiben Sie tatsächlich new <variableName>, wobei variableName ein Body einer Funktion oder Klasse ist, die in einem Modul definiert und exportiert wird. Um diese Funktion/Klasse der Variablen require() zuzuordnen.

Anstatt also

const type = 'Square'; 
const aSquare = new type(); 

müssen Sie schreiben:

const type = 'Square'; 
const shape = require(`${pathToShapeModules}/${type}.js`); 
const aShape = new shape(); 

Minor Nachteil ist, dass eslint beklagt (in einigen Regeleinstellungen), dass require s oben auf die platziert werden sollen Modul. Und natürlich braucht es eine korrekte Ausnahmebehandlung durch try ... catch etc. Also wahrscheinlich ist Factory-Lösung besser (also werde ich es akzeptieren), aber ich denke, dass für kleine Spezialfälle diese Lösung in Ordnung ist.

Verwandte Themen