Um die grundlegende Frage zu beantworten - ist dies ein neues Javascript-Fabrikmuster - nein, ist es nicht. (Check out ES6/ES2015, Typescript und Aureliens Dependency Injection-Modul.)
nun die allgemeine Aussage zu beantworten - was Sie im Wesentlichen tun versuchen, Metadaten zu einem „Klasse“ Typ in Javascript hinzuzufügen. Die Sache ist, es sieht so aus, als ob du versuchst, eine Fabrik von Fabriken zu schaffen - was ich nicht sicher bin. (. Vielleicht haben Sie Ihr Beispiel vereinfacht)
Mit Ihrem Beispiel, würde ich etwas mehr tun, wie folgt:
namespace('mynamespace');
// object factory
mynamespace.factory = (function() {
'use strict';
var api = {};
var registry = {};
// register an item
api.register = function (name, item, overwrite) {
if (!overwrite || registry.hasOwnProperty('name')) {
throw new Error ('factory.register(): name collision detected: ' + name);
}
registry[name] = item;
};
// make an item given its name
api.make = function (name) {
var item = registry[name];
return item ? new item() : null; // or better, Object.create(item);
};
return api;
})();
// define a module & register it with factory
mynamespace.factory.register ('FactoryPartA', function FactoryPartA() {
'use strict';
var label = 'Factory Part A'; // private property
this.test = undefined; // public property
this.label = function() { // public method
return label;
};
});
// define a different module & register it with factory
mynamespace.factory.register ('FactoryPartB', function FactoryPartB() {
'use strict';
var label = 'Factory Part B';
this.test = undefined;
this.label = function() {
return label;
};
});
Dieses Zeug die zusätzliche Fabrik entfernt, so dass es kein FactoryFactory ist. (Nicht sicher, warum Sie das hatten.) Außerdem haben Sie eine lineare Suche erwähnt - indem Sie ein Objekt anstelle eines Arrays verwenden, vermeiden Sie eine lineare Suche (Objekt-Hashes sind Konstant-Zeit-Lookup). Schließlich können Sie jeden Namen registrieren, ohne ihn in ein Wrapper-Objekt einfügen zu müssen. Dies ist näher an DI.
Wenn Sie wirklich den Metadaten-Stil Ansatz wollen tun, obwohl, können Sie so etwas wie die folgenden tun:
namespace('mynamespace');
// object factory
mynamespace.factory = (function() {
'use strict';
var api = {};
var registry = {};
// register an item
api.register = function (item, overwrite) {
if (!overwrite || registry.hasOwnProperty(item.name)) {
throw new Error ('factory.register(): name collision detected: ' + item.name);
}
registry[item.name] = item;
};
// make an item given its name
api.make = function (name) {
var item = registry[name];
return item ? new item() : null; // or better, Object.create(item);
};
return api;
})();
// define a module & register it with factory
mynamespace.factory.register (function FactoryPartA() {
'use strict';
var label = 'Factory Part A'; // private property
this.test = undefined; // public property
this.label = function() { // public method
return label;
};
});
// define a different module & register it with factory
mynamespace.factory.register (function FactoryPartB() {
'use strict';
var label = 'Factory Part B';
this.test = undefined;
this.label = function() {
return label;
};
});
Dies verwendet die Funktionsnamen anstelle eine separate Eigenschaft. (Funktionen können in Javascript benannt oder anonymisiert werden. Diese Methode würde nicht mit anonymen Funktionen funktionieren.) Ich erwähnte Typescript oben, da Typoskript, wenn es in Javascript kompiliert, tatsächlich viele eigene Metadaten auf Objekte legt, ähnlich wie Sie es tun .Ich erwähnte die Abhängigkeitsinjektion von Aurelia, weil die Funktionalität @autoinject
diese Metadaten tatsächlich liest, um Objekte zu erstellen, ähnlich wie Sie es tun.
Aber wirklich .... es sei denn, Sie versuchen, einen Dependency-Injektionscontainer zu erstellen (was mehr Logik als in Ihrem Beispiel erfordern würde - Sie möchten einen Container mit Schlüsseln, die auch auf Instanzen verweisen können) würde argumentieren, dass Sie viel mehr Funktionalität aus Object.create()
und Object.assign()
bekommen, als Sie mit diesem Muster würden. Viele Entwurfsmuster, die Sie in einer statisch typisierten, stark typisierten, kompilierten Sprache benötigen, sind außerhalb dieser Umgebung nicht erforderlich. So können Sie das tun:
function PartA() {
'use strict';
var label = 'Factory Part A'; // private property
this.test = undefined; // public property
this.label = function() { // public method
return label;
}
function PartB() {
'use strict';
var label = 'Factory Part B';
this.test = undefined;
this.label = function() {
return label;
};
}
var A = Object.create(PartA);
var B = Object.create(PartB);
Dies ist, einfach, viel einfacher.
Diese Art der dynamischen Factory-Verknüpfung ist genau das Problem Abhängigkeitsinjektion wurde erstellt, um zu lösen ([schamlose Link zu meiner eigenen Bibliothek] (https://github.com/ssube/noicejs)). – ssube