Patterns – Muster auf Deutsch. Informatiker fassen gerne Probleme in Muster um sie zu katalogisieren. Eine Problemlösung kann so öfter wieder verwendet werden, Fehler werden vermieden. Manchmal stellen sie auch einfach einen Weg dar etwas elegant zu lösen. Besonders in objektorientierter Programmierung sind solche Muster bekannt: Entwurfsmuster.
Nachdem ich mich jetzt während des Sommers mit Objektorientierung, Softwarearchitektur und Entwurfsmustern beschäftigt hatte, suchte ich auch in JavaScript nach Mustern und Best Practice, und nun möchte ich diese Erfahrungen auf meinem Blog teilen.
Weiterlesen „JavaScript OOP: patterns“
Ich kam noch nie dazu hier einen Codefetzen vorzustellen (außer des Beitrags zum Dekorierer). Nun nutze ich diese Gelegenheit eine meiner ersten JavaScript Klassen zu besprechen.
Gleichzeitig handelt es sich um das Muster Wertobjekt (ValueObject), welches unveränderlich ist.
Vorweg muss noch gesagt werden, dass alle Attribute als Konvention protected gelten, public wird nicht benötigt und private lässt sich über Closures realisieren. Einfache Attribute tragen zudem den Anfangsbuchstaben ihres Typs (z.B. s für String).
Objekte der Klasse stellen eine Menge eines Rohstoffs dar.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
function Resource(amount, type) {
var nAmount = amount;
var sType = type;
if (amount < 0) {
throw new IllegalArgumentException( "amount has to be positive" );
}
this .getAmount = function () {
return nAmount;
};
this .getType = function () {
return sType;
};
}
Resource.prototype.plus = function (resource) {
if (!(resource instanceof Resource && this .getType() == resource.getType())) {
throw new IllegalArgumentException( "resources don't match." );
}
var newRes = Object.create( this );
Resource.call(newRes, this .getAmount() + resource.getAmount(), this .getType());
return newRes;
};
Resource.prototype.minus = function (resource) {
if (!(resource instanceof Resource && this .getType() == resource.getType())) {
throw new IllegalArgumentException( "resources don't match." );
}
if ( this .getAmount() < resource.getAmount()) {
throw new IllegalArgumentException( "can't substract a higher amount" );
}
var newRes = Object.create( this );
Resource.call(newRes, this .getAmount() - resource.getAmount(), this .getType());
return newRes;
};
|
Interessant ist vor allem die Stelle, an der dynamisch neue Objekte der selben Klasse zurückgegeben werden (plus() und minus()), ich möchte Resource noch erweitern können und evtl. für die verschiedenen Rohstoffsorten eigene Klassen ableiten, daher sollten diese Methoden dann nicht nach einer mathematischen Operation auf die Klasse Resource zurückschrumpfen. In PHP kann man „new“ einfach einen String übergeben, in Java muss man einen Umweg über eine Factory oder Reflection machen.
In JavaScript bietet es sich an, das momentane Objekt als Prototyp für das neue zu verwenden und dieses durch den Resource Konstruktor zu initialisieren.
Ich weiß noch nicht, ob mir dieses Pattern noch öfter begegnen wird, aber vor allem bei Wertobjekten (ValueObject), die mit Vererbung erweiterbar bleiben sollen ist dies praktisch. Allgemein wenn man ein neues Objekt des selben Typs wie das momentane zurückgeben möchte.
Jetzt kann ich eine Kindklasse ResourceContainer schreiben, die noch Funktionalität für Gewicht und Volumen des Rohstoffs bereitstellt (z.B zum Beladen von Schiffen):
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
function ResourceContainer(amount, type) {
Resource.call( this , amount, type);
}
ResourceContainer.prototype = Object.create(Resource.prototype);
Resource.DESITY.metal = 7.85;
Resource.WEIGHT.metal = 1000;
ResourceContainer.prototype.getWeight = function () {
return this .getAmount() * Resource.WEIGHT[ this .getType()];
};
ResourceContainer.prototype.getVolume = function () {
return this .getAmount() * Resource.DENSITY[ this .getType()];
};
|
Ich beginne langsam die Prototypennatur von JavaScript zu verwenden, bin aber immer noch sehr von Klassen von PHP und Java geprägt.