Dekorationsmuster: Erweitern Sie Objektfunktionen dynamisch, ohne die ursprüngliche Klasse und Vererbung zu ändern, und implementieren Sie ein neues Objekt mit derselben Schnittstelle wie das ursprüngliche Objekt, indem Sie ein Objekt umschließen.
Merkmale des Dekoratormusters:
1. Funktionalität hinzufügen, ohne die ursprüngliche Struktur des Originalobjekts zu ändern.
2. Das dekorierte Objekt und das Originalobjekt verfügen über dieselbe Schnittstelle, sodass Kunden das dekorierte Objekt auf die gleiche Weise wie das Originalobjekt verwenden können.
3. Das Dekorationsobjekt enthält einen Verweis auf das Originalobjekt, das heißt, das Dekorationsobjekt ist ein verpacktes Objekt des echten Originalobjekts.
Detaillierte Erklärung des Javascript-Dekoratormusters:
Im Dekoratormuster können dem Objekt zur Laufzeit zusätzliche Funktionen dynamisch hinzugefügt werden. Dies kann beim Umgang mit statischen Klassen eine Herausforderung sein. Da Objekte in Javascript veränderbar sind, ist der Prozess des Hinzufügens von Funktionalität zu einem Objekt an sich kein Problem.
Eine der praktischen Funktionen des Decorator-Musters ist die anpassbare und konfigurierbare Natur seines beabsichtigten Verhaltens. Sie können mit einem normalen Objekt mit nur einigen Grundfunktionen beginnen und dann aus dem Pool verfügbarer Dekorationsressourcen auswählen, welche Funktionen Sie zur Verbesserung des normalen Objekts benötigen, und diese der Reihe nach dekorieren, insbesondere wenn die Reihenfolge der Dekoration wichtig ist.
Eine Möglichkeit, das Dekoratormuster zu implementieren, besteht darin, jeden Dekorator zu einem Objekt zu machen, und dieses Objekt enthält Methoden, die überladen werden sollten. Jeder Dekorateur erbt tatsächlich das Objekt, das vom vorherigen Dekorator erweitert wurde. Jede Dekoratormethode ruft dieselbe Methode für das „geerbte Objekt“ auf und erhält seinen Wert, außerdem führt sie weiterhin einige Vorgänge aus.
Beginnen wir mit Beispiel 1:
//需要装饰的类(函数) function Macbook() { this.cost = function () { return 1000; }; } //计算商品的包装费 function PackagingFee(macbook) { this.cost = function () { return macbook.cost() + 75; }; } //计算商品的运费 function Freight(macbook) { this.cost = function () { return macbook.cost() + 300; }; } //计算商品的保险费用 function Insurance(macbook) { this.cost = function () { return macbook.cost() + 250; }; } // 用法 var myMacbook = new Insurance(new Freight(new PackagingFee(new Macbook()))); console.log(myMacbook.cost());//1625
Im obigen Code sind insgesamt vier Funktionen definiert (. Eine Funktion, die geändert werden muss, drei Funktionen, die zur Änderung verwendet werden.
Dann deklarieren Sie eine Variable myMacbook, um auf das neue Insurance-Objekt zu verweisen. Die formalen Parameter des Freight-Objekts verweisen auf das neue PackagingFee-Objekt Parameter des PackagingFee-Objekts verweisen auf new aus dem Macbook-Objekt.
Als nächstes rufen Sie die Kostenmethode von myMacbook auf. Aus der obigen Analyse können wir schließen, dass der Wert von myMacbook.cost() gleich (der Kostenmethode des Freight-Objekts + 250) und die Kostenmethode des Freight-Objekts gleich (der Kostenmethode des PackagingFee-Objekts) ist + 300) und die Kostenmethode des PackagingFee-Objekts ist gleich (Kostenmethode des Macbook-Objekts +75).
Das Endergebnis ist also: der Wert von myMacbook.cost() = 250 + (300 + (75 + 1000)) = 1625.
// 用法 var myMacbook = new Insurance(new Freight(new PackagingFee(new Macbook()))); console.log(myMacbook.cost());//1625 //上面的代码等价于下面拆分后的代码,或许拆分后代码你更能看出前后的逻辑性 var macbook = new Macbook(); var package = new PackagingFee(macbook); var freight = new Freight(package); var myMacbook = new Insurance(freight); //当然,如果你不想声明这么多变量(macbook、package、freight),只用一个变量也是可以的 var macbook = new Macbook(); macbook = new PackagingFee(macbook); macbook = new Freight(macbook); var myMacbook = new Insurance(macbook);
Schauen Sie sich noch einmal Instanz 2 an:
function ConcreteClass() { this.performTask = function () { this.preTask(); console.log('doing something'); this.postTask(); }; } function AbstractDecorator(decorated) { this.performTask = function () { decorated.performTask(); }; } function ConcreteDecoratorClass(decorated) { this.base = AbstractDecorator; this.base(decorated);// add performTask method decorated.preTask = function () { console.log('pre-calling..'); }; decorated.postTask = function () { console.log('post-calling..'); }; } var concrete = new ConcreteClass(); var decorator1 = new ConcreteDecoratorClass(concrete); decorator1.performTask(); //pre-calling.. //doing something //post-calling..
Instanz 2 ist eigentlich dasselbe wie Instanz 1 Sehr ähnlich, lassen Sie es uns kurz analysieren. Zunächst werden in Beispiel 2 drei Funktionen definiert, dann werden zwei Variablen konkret und decorator1 deklariert und schließlich wird die performTask-Methode von decorator1 aufgerufen.
Auf den ersten Blick scheint es, dass es in ConcreteDecoratorClass keine performTask-Methode gibt. Analysieren wir zunächst die folgenden zwei Codezeilen:
var concrete = new ConcreteClass(); //声明一个变量concrete指向new出来的ConcreteClass对象 var decorator1 = new ConcreteDecoratorClass(concrete); //声明一个变量decorator1指向new出来的ConcreteDecoratorClass对象,并传入变量concrete作为形参
Anschließend analysieren wir den Code in der ConcreteDecoratorClass-Funktion Zeile für Zeile:
this.base = AbstractDecorator; //定义一个当前对象(decorator1)的base属性,并指向函数AbstractDecorator this.base(decorated); //调用base属性指向的函数,也就是调用AbstractDecorator函数,同时传入形参decorated,形参decorated指向new出来的ConcreteClass对象
Apropos, es scheint, dass es in der ConcreteDecoratorClass-Funktion immer noch keine performTask-Methode gibt. Der entscheidende Punkt ist, sich „dies“ anzusehen!
Dies in der ConcreteDecoratorClass-Funktion zeigt auf das neue ConcreteDecoratorClass-Objekt (d. h. es zeigt auf dasselbe Objekt wie decorator1);
Der Schlüssel dazu in der AbstractDecorator-Funktion besteht darin, zu sehen, welches Objekt ruft diese Funktion auf, auf die dieses Objekt zeigt (aus dem Code „this.base = AbstractDecorator; this.base(decorated);“ können wir sehen, dass das ConcreteDecoratorClass-Objekt neu von die AbstractDecorator-Funktion aufruft), In der AbstractDecorator-Funktion zeigt dies also auf das neue ConcreteDecoratorClass-Objekt (zeigt auch auf dasselbe Objekt wie decorator1).
Zusammenfassend stellen wir fest, dass im obigen Code Ob dies in der ConcreteDecoratorClass-Funktion oder dies in der AbstractDecorator-Funktion ist, sie alle auf das neue ConcreteDecoratorClass-Objekt verweisen.
Wenn wir also decorator1.performTask() ausführen, wird weiterhin der Code in der anonymen Funktion (decorated.performTask();) und der dekorierte formale Parameter in den anonymen Funktionspunkten ausgeführt zum neuen ConcreteClass-Objekt und führen Sie die performTask-Methode des Objekts aus.
Schauen Sie sich zum Schluss Beispiel 3 an:
var tree = {}; tree.decorate = function () { console.log('Make sure the tree won\'t fall'); }; tree.getDecorator = function (deco) { tree[deco].prototype = this; return new tree[deco]; }; tree.RedApples = function () { this.decorate = function () { this.RedApples.prototype.decorate(); // 第7步:先执行原型(这时候是Angel了)的decorate方法 console.log('Add some red apples'); // 第8步 再输出 red // 将这2步作为RedApples的decorate方法 } }; tree.BlueApples = function () { this.decorate = function () { this.BlueApples.prototype.decorate(); // 第1步:先执行原型的decorate方法,也就是tree.decorate() console.log('Put on some blue apples'); // 第2步 再输出blue // 将这2步作为BlueApples的decorate方法 } }; tree.Angel = function () { this.decorate = function () { this.Angel.prototype.decorate(); // 第4步:先执行原型(这时候是BlueApples了)的decorate方法 console.log('An angel on the top'); // 第5步 再输出angel // 将这2步作为Angel的decorate方法 } }; tree = tree.getDecorator('BlueApples'); // 第3步:将BlueApples对象赋给tree,这时候父原型里的getDecorator依然可用 tree = tree.getDecorator('Angel'); // 第6步:将Angel对象赋给tree,这时候父原型的父原型里的getDecorator依然可用 tree = tree.getDecorator('RedApples'); // 第9步:将RedApples对象赋给tree tree.decorate(); // 第10步:执行RedApples对象的decorate方法 //Make sure the tree won't fall //Add blue apples //An angel on the top //Put on some red apples
Beispiel 3 sieht tatsächlich sehr kompliziert aus Aus den beiden vorherigen Beispielen ist ersichtlich, dass in Beispiel 3 insgesamt 5 Funktionsausdrücke deklariert sind. Konzentrieren wir uns auf die Analyse des folgenden Codes:
//tree.getDecorator('BlueApples')返回new出来的tree.BlueApples的实例对象,并将该对象赋值给空的tree对象 tree = tree.getDecorator('BlueApples'); //new出来的tree.BlueApples的实例对象的原型指向 --> 空对象tree //tree.getDecorator('Angel')返回new出来的tree.Angel的实例对象(这行代码中的第二个tree已经是上面一行代码运行结果后的tree.BlueApples的实例对象) tree = tree.getDecorator('Angel'); //new出来的tree.Angel的实例对象的原型指向 --> tree.BlueApples的实例对象 //tree.getDecorator('RedApples')返回new出来的tree.RedApples的实例对象(这行代码中的第二个tree已经是上面一行代码运行结果后的tree.Angel的实例对象) tree = tree.getDecorator('RedApples'); //new出来的tree.RedApples的实例对象的原型指向 --> tree.Angel的实例对象 //调用tree.decorate(),这里的tree已经是new出来的tree.RedApples的实例对象了。 //tree.RedApples的实例对象的decorate属性方法里面的第一行代码是 “this.RedApples.prototype.decorate()” //结合上面的分析可以得出以下的原型链结构: //this.RedApples.prototype --> tree.Angel; //tree.Angel.prototype --> tree.BlueApples; //tree.BlueApples.prototype --> 空对象tree tree.decorate();
Nach der Analyse ist es nicht schwer, das endgültige Ausgabeergebnis zu ermitteln.
Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Eigenschaften und Anwendungsbeispiele des Javascript-Dekoratormusters. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!