Heim > Web-Frontend > js-Tutorial > Entwurfsmuster für umfangreiche JavaScript-Anwendungsarchitekturen (Fortgeschritten)

Entwurfsmuster für umfangreiche JavaScript-Anwendungsarchitekturen (Fortgeschritten)

亚连
Freigeben: 2018-05-21 09:23:51
Original
2634 Leute haben es durchsucht

Das Folgende ist ein umfangreiches Entwurfsmuster für eine JavaScript-Anwendungsarchitektur, das ich für Sie zusammengestellt habe. Interessierte Studenten können einen Blick darauf werfen.

Das Folgende sind die Hauptkapitel dieses Artikels:

1. Was ist ein „JavaScript-Großprogramm“?

2. Betrachten Sie die aktuelle Programmarchitektur

3. Denken Sie über die Zukunft nach

Vorgeschlagene Architektur

5.1 Designmuster

5.1.1 Modultheorie

5.1.1.1 Übersicht

5.1.1.2 Modulmodus

5.1.1.3 Selbstgesichtswert des Objekts

5.1.1.4 CommonJS-Modul

5.1.2 Fassadenmodus

5.1.3 Vermittlermodus

5.2 Auf Ihre Architektur anwenden

5.2 .1 Fassade – Kernabstraktion

5.2.2 Vermittler – Programmkern

5.2.3 Eng zusammenarbeiten

6. Erweiterung des Veröffentlichens/Abonnements für Sub: automatische Registrierung Ereignisse

7. Fragen und Antworten

8. Danksagungen

Was ist ein „JavaScript-Großprogramm“?

Bevor wir beginnen, definieren wir, was eine große JavaScript-Site ist. Viele erfahrene JS-Entwicklungsexperten sind ebenfalls der Ansicht, dass mehr als 100.000 Zeilen JavaScript-Code gelten sagen, dass JavaScript-Code größer als 1 MB sein muss. Tatsächlich ist keines der beiden korrekt, da es nicht an der Menge des installierten Codes gemessen werden kann. Viele triviale JS-Codes können leicht 100.000 Zeilen überschreiten.

Meine Definition von „groß“ lautet wie folgt:

Ich persönlich denke, dass große JavaScript-Programme sehr wichtig sein sollten Integriert in Es ist ein Programm, das die Bemühungen vieler herausragender Entwickler nutzt, um schwere Daten zu verarbeiten und im Browser anzuzeigen.

Überprüfung der aktuellen Programmarchitektur

Ich kann nicht genug betonen, wie wichtig diese Frage ist, viele erfahrene Entwickler sagen oft: „Bestehende Ideen und Designmuster haben sehr gut funktioniert.“ Bei meinem letzten mittelgroßen Projekt sollte es also kein Problem sein, es in einem etwas größeren Programm erneut zu verwenden, oder? Es gibt große Bedenken, die aufgeschlüsselt und beachtet werden müssen. Ich werde kurz erklären, dass es Zeit braucht, die Programmarchitektur zu überprüfen, die schon seit langem läuft. In den meisten Fällen sollte die aktuelle JavaScript-Programmarchitektur wie folgt aussehen (beachten Sie, dass es sich um eine JS-Architektur handelt, nicht um die ASP.NET MVC, die wir oft nennen):

benutzerdefinierte Widgets

Modelle
Ansichten
Controller
Vorlagen
Bibliotheken/Toolkits
ein Anwendungskern.

Sie können das Programm auch separat in mehrere Module kapseln oder andere Entwurfsmuster verwenden, was gut ist, aber wenn diese Strukturen vorhanden sind Stellen Sie Ihre Architektur vollständig dar. Schauen wir uns einige wichtige Punkte an:

1. Wie viele Dinge können sofort wiederverwendet werden?

Gibt es separate Module, die nicht von anderem Code abhängen? Ist es in sich geschlossen? Wenn ich zu der von Ihnen verwendeten Codebasis gehe, zufällig einen Modulcode auswähle und ihn dann auf einer neuen Seite einfüge, ist er dann sofort verfügbar? Sie können sagen, dass das Prinzip ausreicht. Wenn Ihr Unternehmen bereits viele wichtige Programme entwickelt hat, sagt eines Tages jemand, dass das Chat-Modul gut ist Fügen Sie es in ein anderes Projekt ein, können Sie es einfach verwenden, ohne den Code zu ändern?

2. Wie viele Module im System hängen von anderen Modulen ab?

Sind die verschiedenen Module des Systems eng miteinander verbunden? Bevor ich diese Frage als Problem anspreche, möchte ich zunächst erklären, dass dies nicht bedeutet, dass alle Module keine Abhängigkeiten haben dürfen. Beispielsweise kann eine feinkörnige Funktion von der Basisfunktion erweitert werden Ich spreche von den Abhängigkeiten zwischen verschiedenen Funktionsmodulen. Theoretisch sollten nicht alle verschiedenen Funktionsmodule zu viele Abhängigkeiten haben.

3. Wenn ein bestimmter Teil Ihres Programms ausfällt, können andere Teile trotzdem funktionieren?

Wenn Sie ein Programm ähnlich wie Gmail erstellen, können Sie feststellen, dass viele Module in Gmail dynamisch geladen werden. Beispielsweise wird das Chat-Modul nicht geladen, wenn die Seite initialisiert wird, und selbst wenn nach dem Laden ein Fehler auftritt, wird die Seite nicht geladen Andere Teile können auch normal verwendet werden.

4. Kann jedes Ihrer Module problemlos getestet werden? Jedes Ihrer Module kann auf einer großen Site mit Millionen von Benutzern oder sogar von mehreren Sites verwendet werden. Daher muss Ihr Modul Tests standhalten können, d. h. es sollte einfach sein, ob es sich innerhalb der Architektur befindet um zu testen, ob es außerhalb der Architektur liegt, einschließlich der Tatsache, dass die meisten Behauptungen in verschiedenen Umgebungen gültig sein können.

Denken Sie langfristig

Beim Aufbau eines großen Programms ist es am wichtigsten, vorausschauend zu sein. Man kann die Situation nicht nur einen Monat lang betrachten oder in einem Jahr, aber denken Sie auch an die Zukunft. Welche Möglichkeiten für Veränderungen gibt es langfristig? Entwickler binden den DOM-Manipulationscode oft zu eng an das Programm, obwohl sie manchmal separate Logik in verschiedene Module gekapselt haben. Warum ist das auf lange Sicht nicht gut?

Ein Kollege von mir hat einmal gesagt, dass eine präzise Architektur für zukünftige Szenarien möglicherweise nicht geeignet ist. Das stimmt manchmal, aber wenn man es tun muss, muss man ziemlich viel bezahlen. Beispielsweise müssen Sie aus bestimmten Leistungs-, Sicherheits- und Designgründen zwischen Dojo, jQuery, Zepto und YUI wählen und diese ersetzen. Zu diesem Zeitpunkt gibt es Abhängigkeiten, die Geld und Zeit erfordern . , wir brauchen Leute, oder?

Für einige kleine Websites ist das in Ordnung, aber große Websites müssen wirklich einen flexibleren Mechanismus bereitstellen, ohne sich um verschiedene Probleme zwischen verschiedenen Modulen kümmern zu müssen. Dies spart nicht nur Geld, sondern auch Zeit.

Um es zusammenzufassen: Sind Sie jetzt sicher, dass Sie einige Klassenbibliotheken ersetzen können, ohne das gesamte Programm neu zu schreiben? Wenn nicht, dann denke ich, dass das, worüber wir unten sprechen werden, besser für Sie geeignet ist.

Viele erfahrene JavaScript-Entwickler gaben einige wichtige Anmerkungen:

Justin Meyer, Autor von JavaScriptMVC, sagte:

Das Erstellen großer Programme ist das größte Geheimnis niemals große Programme zu erstellen, sondern das Programm in kleine Module zu unterteilen, sodass jedes kleine Modul getestet, dimensioniert und dann in das Programm integriert werden kann.

Nicholas, Zakas, Autor von Hochleistungs-JavaScript-Websites:
„Der Schlüssel liegt darin, von Anfang an anzuerkennen, dass man keine Ahnung hat, wie sich das entwickeln wird. Wenn man akzeptiert, dass man nicht alles weiß.“ , Sie beginnen, das System defensiv zu gestalten, was oft sehr einfach ist, wenn Sie ein wenig Zeit investieren. Sie sollten beispielsweise damit rechnen, dass jeder Teil der App mit einem anderen kommuniziert Das System wird sich wahrscheinlich ändern, also müssen Sie das abstrahieren.“ -

Viele Textprobleme sind zu mühsam. Zusammenfassend lässt sich sagen, dass alles veränderbar ist, also muss es abstrakt sein.

JQuery Fundamentals-Autorin Rebecca Murphey:
Je enger die Verbindung zwischen den einzelnen Modulen, desto weniger wiederverwendbar und desto schwieriger ist es, sie zu ändern.

Diese wichtigen Punkte oben sind die Kernelemente beim Aufbau einer Architektur, und wir müssen sie jederzeit im Auge behalten.

Brainstorming

Lassen Sie uns eine lose gekoppelte Architektur erstellen. Es gibt keine Abhängigkeiten zwischen Modulen und dann in der Mitte übernimmt und verarbeitet das Feedback entsprechender Nachrichten.

Wenn wir beispielsweise ein JavaScript zum Erstellen eines Online-Bäckereiprogramms haben, sendet ein Modul eine Nachricht, die möglicherweise lautet: „42 Brötchen müssen geliefert werden.“ Wir verwenden verschiedene Schichten, um die vom Modul gesendeten Nachrichten wie folgt zu verarbeiten:

Das Modul greift nicht direkt auf den Programmkern zu
Das Modul ruft andere Module nicht direkt auf oder beeinflusst sie nicht direkt

Dadurch wird verhindert, dass wir aufgrund eines Fehlers in einem Modul Fehler in allen Modulen verursachen.

Ein weiteres Problem ist die Sicherheit. Die reale Situation ist, dass die meisten Menschen nicht glauben, dass die innere Sicherheit ein Problem darstellt. Wir sagen in unserem Herzen, dass ich das Programm selbst erstellt habe und weiß, welche öffentlich sind und welche sind privat. Die Sicherheit stellt kein Problem dar, aber gibt es eine Möglichkeit zu definieren, welches Modul die Berechtigung hat, auf den Kern des Programms zuzugreifen? Wenn es beispielsweise ein Chat-Modul gibt, möchte ich nicht, dass es das Admin-Modul aufruft, oder ich möchte nicht, dass es ein Modul mit DB-Schreibberechtigungen aufruft, da dies sehr fragil ist und leicht zu XSS-Angriffen führen kann . Nicht jedes Modul sollte in der Lage sein, alles zu tun, aber das ist das Problem mit JavaScript-Code in den meisten aktuellen Architekturen. Stellen Sie eine mittlere Ebene bereit, um zu steuern, welches Modul auf den autorisierten Teil zugreifen kann. Mit anderen Worten, das Modul kann nur den autorisiertesten Teil ausführen.

Vorgeschlagene Architektur

Der Schwerpunkt unseres Artikels liegt hier. Diesmal verwendet unsere vorgeschlagene Architektur Designmuster, die wir alle kennen: Modul, Fassade und Vermittler.

Anders als beim herkömmlichen Modell lassen wir das Modul nur einige Ereignisse veröffentlichen, um die einzelnen Module zu entkoppeln. Der Mediatormodus kann dafür verantwortlich sein, Nachrichten von diesen Modulen zu abonnieren und dann die Reaktion der Benachrichtigung zu steuern , Fassadenmodus Benutzer beschränken die Berechtigungen jedes Moduls.

Die folgenden Teile müssen wir beachten:
1 Entwurfsmuster
1.1 Modultheorie
1.1.1 Übersicht
1.1.2 Modulmodus
1.1.3 Objekt seit Nennwert
Fassadenmustermediator - Programmkern
2.3 Integration der Integration, wie es funktioniert


Modultheorie

Jeder kann einen modularen Code für einen größeren oder ein größerer oder verwendet haben In geringerem Umfang ist ein Modul Teil einer vollständigen und robusten Programmarchitektur. Nehmen wir ein Beispiel: Das Chat-Modul besteht aus vielen separaten Teilen Untermodule: Das darin enthaltene Emoticon-Modul ist eigentlich ein separater Teil. Das Untermodul wird auch im Fenster zum Versenden von E-Mails verwendet.

Das andere ist, dass Module dynamisch geladen, gelöscht und ersetzt werden können.

In JavaScript gibt es mehrere Möglichkeiten, Module zu implementieren. Die bekanntesten sind Modulmodus und Objektliterale. Wenn Sie damit bereits vertraut sind, ignorieren Sie bitte diesen Abschnitt und springen Sie direkt zum CommonJS-Teil.

Modulmuster

Modulmuster ist ein beliebtes Entwurfsmuster, das private Variablen, Methoden und Zustände durch Umschließen dieser Inhalte, im Allgemeinen globale Objekte, kapseln kann Es kann nicht direkt darauf zugegriffen werden. In diesem Entwurfsmuster wird nur eine API zurückgegeben und alle anderen Inhalte werden als privat gekapselt.

Außerdem ähnelt dieser Modus dem selbstausführenden Funktionsausdruck. Der einzige Unterschied besteht darin, dass das Modul ein Objekt zurückgibt, während der selbstausführende Funktionsausdruck eine Funktion zurückgibt.

Wie wir alle wissen, verfügt JavaScript nicht über Zugriffsmodifikatoren. Es kann nicht für jedes Feld oder jede Methode private und öffentliche Modifikatoren deklarieren. Das heißt, ein Objekt zurückzugeben, das einige öffentliche Methoden enthält. Diese Methoden können interne Objekte aufrufen.

Sehen Sie sich den folgenden Code an. Die Deklaration enthält ein globales Korbmodul, sodass Ihr gesamtes Programm nicht gleichzeitig darauf zugreifen kann. Wir haben ein Objekt zurückgegeben, das drei Methoden enthält (z. B. addItem, getItemCount, getTotal). Diese drei Methoden können auf das private Korbarray zugreifen.

var basketModule = (function() {
var basket = []; //private
return { //exposed to public
  addItem: function(values) {
    basket.push(values);
  },
  getItemCount: function() {
    return basket.length;
  },
  getTotal: function(){
    var q = this.getItemCount(),p=0;
    while(q--){
    p+= basket[q].price;
    }
    return p;
  }
 }
}());
Nach dem Login kopieren

Beachten Sie gleichzeitig, dass das von uns zurückgegebene Objekt direkt dem Korbmodul zugewiesen ist, sodass wir es wie folgt verwenden können:

//basketModule is an object with properties which can also be methods
basketModule.addItem({item:'bread',price:0.5});
basketModule.addItem({item:'butter',price:0.3});
 
console.log(basketModule.getItemCount());
console.log(basketModule.getTotal());
 
//however, the following will not work:
console.log(basketModule.basket);// (undefined as not inside the returned object)
console.log(basket); //(only exists within the scope of the closure)
Nach dem Login kopieren

Das ist in verschiedenen beliebten Bibliotheken (wie Dojo, jQuery) Wie geht das?

Dojo

Dojo versucht, dojo.declare zu verwenden, um eine Deklaration im Klassenstil bereitzustellen. Wir können es verwenden, um das Modulmuster zu implementieren. Wenn Sie beispielsweise das Korbobjekt unter dem Store-Namespace deklarieren möchten, können Sie Folgendes tun:

//traditional way
var store = window.store || {};
store.basket = store.basket || {};
 
//using dojo.setObject
dojo.setObject("store.basket.object", (function() {
  var basket = [];
  function privateMethod() {
    console.log(basket);
  }
  return {
    publicMethod: function(){
      privateMethod();
    }
   };
}()));
Nach dem Login kopieren
Verwenden Sie es in Verbindung mit dojo.provide, was sehr leistungsstark ist.

YUI

Der folgende Code ist die ursprüngliche Implementierung von YUI:

YAHOO.store.basket = function () {

 //"private" variables:
 var myPrivateVar = "I can be accessed only within YAHOO.store.basket .";

 //"private" method:
 var myPrivateMethod = function () {
 YAHOO.log("I can be accessed only from within YAHOO.store.basket");
 }

 return {
 myPublicProperty: "I'm a public property.",
 myPublicMethod: function () {
  YAHOO.log("I'm a public method.");

  //Within basket, I can access "private" vars and methods:
  YAHOO.log(myPrivateVar);
  YAHOO.log(myPrivateMethod());

  //The native scope of myPublicMethod is store so we can
  //access public members using "this":
  YAHOO.log(this.myPublicProperty);
 }
 };

} ();
Nach dem Login kopieren

jQuery

Es gibt viele Implementierungen des Modulmusters in jQuery. Schauen wir uns ein anderes Beispiel an, das eine neue Bibliothek deklariert und diese dann beim Erstellen der Bibliothek automatisch ausführt die init-Methode.

function library(module) {
  $(function() {
    if (module.init) {
      module.init();
    }
  });
  return module;
}
 
var myLibrary = library(function() {
  return {
    init: function() {
      /*implementation*/
      }
  };
}());
Nach dem Login kopieren

Objekt-Selbstgesichtswert

Der Objekt-Selbstgesichtswert wird mit geschweiften Klammern deklariert, und es besteht keine Notwendigkeit, das Schlüsselwort new zu verwenden Wenn Ihnen der öffentliche/private Charakter der Attributfelder in einem Modul nicht wichtig ist, können Sie diese Methode verwenden. Beachten Sie jedoch, dass sich diese Methode von JSON unterscheidet. Objekt-Selbstgesicht: var item={name: „tom“, value:123} JSON: var item={“name“: „tom“, „value“:123}.

var myModule = {
 myProperty: 'someValue',
 //object literals can contain properties and methods.
 //here, another object is defined for configuration
 //purposes:
 myConfig: {
 useCaching: true,
 language: 'en'
 },
 //a very basic method
 myMethod: function () {
 console.log('I can haz functionality?');
 },
 //output a value based on current configuration
 myMethod2: function () {
 console.log('Caching is:' + (this.myConfig.useCaching) ? 'enabled' : 'disabled');
 },
 //override the current configuration
 myMethod3: function (newConfig) {
 if (typeof newConfig == 'object') {
  this.myConfig = newConfig;
  console.log(this.myConfig.language);
 }
 }
};

 
myModule.myMethod(); //I can haz functionality
myModule.myMethod2(); //outputs enabled
myModule.myMethod3({ language: 'fr', useCaching: false }); //fr
Nach dem Login kopieren

CommonJS

Ich werde hier nicht viel über die Einführung von CommonJS sagen, es wurde in vielen früheren Artikeln vorgestellt, also wir Darüber hinaus gibt es im CommonJS-Standard zwei wichtige Parameter: exports und require Exports stellen die zu ladenden Module dar, und require bedeutet, dass diese geladenen Module von anderen Modulen abhängen und auch geladen werden müssen .

/*
Example of achieving compatibility with AMD and standard CommonJS by putting boilerplate around the standard CommonJS module format:
*/
 
(function(define){
  define(function(require,exports){
    // module contents
    var dep1 = require("dep1");
    exports.someExportedFunction = function(){...};
    //...
  });
})(typeof define=="function"?define:function(factory){factory(require,exports)});
Nach dem Login kopieren
Es gibt viele CommonJS-Standard-Modulladeimplementierungen. Ich bevorzuge RequireJS. Es kann sehr gut Module und verwandte abhängige Module laden Laden Sie zuerst das Encoder-Modul und rufen Sie dann seine encodeToASCII-Methode ab. Theoretisch sollte der Code wie folgt aussehen:
var encodeToASCII = require("encoder").encodeToASCII;
exports.encodeSomeSource = function(){
  //其它操作以后,然后调用encodeToASCII
}
Nach dem Login kopieren

但是上述代码并没用工作,因为encodeToASCII函数并没用附加到window对象上,所以不能使用,改进以后的代码需要这样才行:

define(function(require, exports, module) {
  var encodeToASCII = require("encoder").encodeToASCII;
    exports.encodeSomeSource = function(){
    //process then call encodeToASCII
  }
});
Nach dem Login kopieren

CommonJS 潜力很大,但是由于大叔不太熟,所以就不过多地介绍了。

Facade模式

Facade模式在本文架构里占有重要角色,关于这个模式很多JavaScript类库或者框架里都有体现,其中最大的作用,就是包括High level的API,以此来隐藏具体的实现,这就是说,我们只暴露接口,内部的实现我们可以自己做主,也意味着内部实现的代码可以很容易的修改和更新,比如今天你是用jQuery来实现的,明天又想换YUI了,这就非常方便了。

下面这个例子了,可以看到我们提供了很多私有的方法,然后通过暴露一个简单的 API来让外界执行调用内部的方法:

var module = (function () {
 var _private = {
 i: 5,
 get: function () {
  console.log('current value:' + this.i);
 },
 set: function (val) {
  this.i = val;
 },
 run: function () {
  console.log('running');
 },
 jump: function () {
  console.log('jumping');
 }
 };
 return {
 facade: function (args) {
  _private.set(args.val);
  _private.get();
  if (args.run) {
  _private.run();
  }
 }
 }
} ());

module.facade({run:true, val:10});
//outputs current value: 10, running
Nach dem Login kopieren

Facade和下面我们所说的mediator的区别是,facade只提供现有存在的功能,而mediator可以增加新功能。

Mediator模式

讲modiator之前,我们先来举个例子,机场飞行控制系统,也就是传说中的塔台,具有绝对的权利,他可以控制任何一架飞机的起飞和降落时间以及地方,而飞机和飞机之前不允许通信,也就是说塔台是机场的核心,mediator就相当于这个塔台。

mediator就是用在程序里有多个模块,而你又不想让各个模块有依赖的话,那通过mediator模式可以达到集中控制的目的。实际场景中也是,mediator封装了很多不想干的模块,让他们通过mediator联系在一起,同时也松耦合他们,使得他们之间必须通过mediator才能通信。

那mediator模式的优点是什么?那就是解耦,如果你之前对观察者模式比较了解的话,那理解下面的mediator图就相对简单多了,下图是一个high level的mediator模式图:

Entwurfsmuster für umfangreiche JavaScript-Anwendungsarchitekturen (Fortgeschritten)

想想一下,各模块是发布者,mediator既是发布者又是订阅者。

Module 1向Mediator广播一个实际,说需要做某事
Mediator捕获消息以后,立即启动处理该消息需要使用的Module 2,Module 2处理结束以后返回信息给Mediator
与此同时,Mediator也启动了Module 3,当接受Module 2 返回消息的时候自动记录日志到Module 3里

可以看到,各模块之间并没有通信,另外Mediator也可以实现监控各模块状态的功能,例如如果Module 3出错了,Mediator可以暂时只想其它模块,然后重启Module 3,然后继续执行。

回顾一下,可以看到,Mediator的优点是:松耦合的模块由同一的Mediator来控制,模块只需要广播和监听事件就可以了,而模块之间不需要直接联系,另外,一次信息的处理可以使用多个模块,也方便我们以后统一的添加新的模块到现有的控制逻辑里。

确定是:由于所有的模块直接都不能直接通信,所有相对来说,性能方面可能会有少许下降,但是我认为这是值得的。

我们根据上面的讲解来一个简单的Demo:

var mediator = (function(){
 var subscribe = function(channel, fn){
 if (!mediator.channels[channel]) mediator.channels[channel] = [];
 mediator.channels[channel].push({ context: this, callback: fn });
 return this;
 },
 
 publish = function(channel){
 if (!mediator.channels[channel]) return false;
 var args = Array.prototype.slice.call(arguments, 1);
 for (var i = 0, l = mediator.channels[channel].length; i < l; i++) {
  var subscription = mediator.channels[channel][i];
  subscription.callback.apply(subscription.context, args);
 }
 return this;
 };
 
 return {
 channels: {},
 publish: publish,
 subscribe: subscribe,
 installTo: function(obj){
  obj.subscribe = subscribe;
  obj.publish = publish;
 }
 };
 
}());
Nach dem Login kopieren

然后有2个模块分别调用:

//Pub/sub on a centralized mediator
 
mediator.name = "tim";
mediator.subscribe(&#39;nameChange&#39;, function(arg){
 console.log(this.name);
 this.name = arg;
 console.log(this.name);
});
 
mediator.publish(&#39;nameChange&#39;, &#39;david&#39;); //tim, david
 
 
//Pub/sub via third party mediator
 
var obj = { name: &#39;sam&#39; };
mediator.installTo(obj);
obj.subscribe(&#39;nameChange&#39;, function(arg){
 console.log(this.name);
 this.name = arg;
 console.log(this.name);
});
 
obj.publish(&#39;nameChange&#39;, &#39;john&#39;); //sam, john
Nach dem Login kopieren

应用Facade: 应用程序核心的抽象

一个facade是作为应用程序核心的一个抽象来工作的,在mediator和模块之间负责通信,各个模块只能通过这个facade来和程序核心进行通信。作为抽象的职责是确保任何时候都能为这些模块提供一个始终如一的接口(consistent interface),和sendbox controller的角色比较类似。所有的模块组件通过它和mediator通信,所以facade需要是可靠的,可信赖的,同时作为为模块提供接口的功能,facade还需要扮演另外一个角色,那就是安全控制,也就是决定程序的哪个部分可以被一个模块访问,模块组件只能调用他们自己的方法,并且不能访问任何未授权的内容。例如,一个模块可能广播dataValidationCompletedWriteToDB,这里的安全检查需要确保该模块拥有数据库的写权限。

总之,mediator只有在facade授权检测以后才能进行信息处理。

应用Mediator:应用程序的核心

Der Mediator ist die Kernaufgabe der Bewerbung. Lassen Sie uns kurz über seine Aufgaben sprechen. Die Kernaufgabe besteht darin, den Lebenszyklus des Moduls zu verwalten. Wenn dieser Kern alle eingehenden Informationen erfasst, muss er bestimmen, wie das Programm damit umgehen soll – d. h. entscheiden, welches Modul oder welche Module gestartet oder gestoppt werden sollen. Wenn ein Modul gestartet wird, sollte es automatisch ausgeführt werden können, ohne dass der Anwendungskern entscheidet, ob es ausgeführt werden soll (z. B. ob es ausgeführt werden soll, wenn das DOM bereit ist), daher muss das Modul selbst eine Entscheidung treffen.

Möglicherweise haben Sie noch Fragen zu den Umständen, unter denen ein Modul gestoppt wird. Wenn das Programm erkennt, dass ein Modul ausgefallen ist oder ein Fehler aufgetreten ist, muss das Programm eine Entscheidung treffen, um zu verhindern, dass die Methode im Modul weiterhin ausgeführt wird, damit die Komponente neu gestartet werden kann. Der Hauptzweck besteht darin, den Benutzer zu verbessern Erfahrung.

Darüber hinaus sollte der Kern in der Lage sein, Module dynamisch hinzuzufügen oder zu entfernen, ohne andere Funktionen zu beeinträchtigen. Ein häufiges Beispiel ist, dass ein Modul zu Beginn des Seitenladens nicht verfügbar ist, das Modul jedoch nach der Benutzerbedienung dynamisch geladen und ausgeführt werden muss, genau wie die Chat-Funktion in Gmail. Aus Sicht der Leistungsoptimierung sollte dies der Fall sein sehr gut. Verstehe es.

Die Behandlung von Ausnahmefehlern wird ebenfalls vom Anwendungskern übernommen. Wenn jedes Modul Informationen sendet, sendet es außerdem auch alle Fehler an den Kern, sodass der Programmkern diese Module je nach Situation stoppen/neu starten kann. Dies ist auch ein wichtiger Teil der lose gekoppelten Architektur. Wir müssen keine Module manuell ändern. Dies können wir durch die Verwendung von Publish/Subscribe über den Mediator tun.

Zusammenstellen

Jedes Modul enthält verschiedene Funktionen im Programm. Wenn sie Informationen verarbeiten müssen, veröffentlichen sie Informationen, um das Programm zu benachrichtigen (dies ist ihre Hauptverantwortung). Wie im folgenden Abschnitt zur Qualitätssicherung erwähnt, können Module auf einige DOM-Tool-Betriebsmethoden zurückgreifen, sollten jedoch nicht von anderen Modulen des Systems abhängen. Ein Modul sollte sich nicht auf den folgenden Inhalt konzentrieren:

1. Welche Objekt Oder das Modul abonniert die von diesem Modul veröffentlichten Informationen
2. Sind diese Objekte clientseitige Objekte oder serverseitige Objekte
3. Wie viele Objekte haben Ihre Informationen abonniert

Entwurfsmuster für umfangreiche JavaScript-Anwendungsarchitekturen (Fortgeschritten)

Facade abstrahiert den Kern der Anwendung und vermeidet die direkte Kommunikation zwischen Modulen. Es abonniert Informationen von jedem Modul und ist auch für die Autorisierungserkennung verantwortlich, um sicherzustellen, dass jedes Modul über eine eigene Autorisierung verfügt.

Entwurfsmuster für umfangreiche JavaScript-Anwendungsarchitekturen (Fortgeschritten)

Mediator (Anwendungskern) übernimmt die Rolle eines Publish/Subscribe-Managers. Er ist für die Modulverwaltung und das Starten/Stoppen der Modulausführung verantwortlich Modul dynamisch laden und mit Fehlern neu starten.

Entwurfsmuster für umfangreiche JavaScript-Anwendungsarchitekturen (Fortgeschritten)

Das Ergebnis dieser Architektur ist: Es gibt keine Abhängigkeiten zwischen Modulen. Aufgrund der lose gekoppelten Anwendungen können sie einfach getestet und gewartet werden, und jedes Modul kann problemlos verwaltet werden können in anderen Projekten wiederverwendet und dynamisch hinzugefügt und gelöscht werden, ohne dass sich dies auf das Programm auswirkt.

Erweiterung von Publish/Subscribe: Automatische Ereignisregistrierung

Bei automatischen Registrierungsereignissen müssen bestimmte Namenskonventionen befolgt werden, z. B. wenn ein Modul bei einem Ereignis mit dem Namen messageUpdate auftritt veröffentlicht wird, werden alle Module mit der messageUpdate-Methode automatisch ausgeführt. Für die spezifische Implementierungsmethode gibt es Vor- und Nachteile, die Sie in meinem anderen Beitrag lesen können: Magic Upgraded Version of jQuery Custom Binding.

QA
1. Ist es möglich, den Fassaden- oder ähnlichen Sandbox-Modus nicht zu verwenden?

Obwohl der Entwurf der Architektur vorschlägt, dass die Fassade die Berechtigungsprüfungsfunktion implementieren kann, ist es für den Mediator tatsächlich durchaus möglich, dies zu tun Das heißt, durch Entkopplung wird sichergestellt, dass jedes Modul direkt ist. Es gibt kein Problem bei der Kommunikation mit dem Anwendungskern.

2. Sie haben verbessert, dass das Modul keine direkten Abhängigkeiten haben kann. Bedeutet dies, dass es nicht auf Bibliotheken von Drittanbietern (wie z. B. jQuery) zurückgreifen kann?

Dies ist tatsächlich ein zweiseitiges Problem. Ein Modul kann einige Untermodule oder Basismodule haben, z. B. grundlegende DOM-Manipulationstoolklassen. Parteibibliotheken, aber bitte stellen Sie sicher, dass wir diese problemlos ersetzen können.

3. Ich mag diese Architektur und möchte sie verwenden. Gibt es Codebeispiele, auf die ich verweisen kann?

Ich werde ein Codebeispiel als Referenz für alle erstellen, aber vorher können Sie sich den Beitrag Writing Modular JavaScript von Andrew Burgees ansehen.

4. Wenn das Modul direkt mit dem Anwendungskern kommunizieren muss, ist das machbar?

Technisch gesehen gibt es keinen Grund, warum das Modul jetzt nicht direkt mit dem Anwendungskern kommunizieren kann, aber für die meisten Anwendungserfahrungen ist dies immer noch nicht notwendig. Da Sie sich für diese Architektur entschieden haben, müssen Sie sich an die durch die Architektur definierten Regeln halten.

Ich habe das Obige für Sie zusammengestellt und hoffe, dass es Ihnen in Zukunft hilfreich sein wird.

Verwandte Artikel:

Detaillierte Antworten auf Ereignisse in JS (grafisches Tutorial)

JSON-Objekt in String konvertieren (Detaillierte Antworten auf den Code sind beigefügt)

JS Event Bubbling und Event Capture (grafisches Tutorial, einfache Gewalt)

Das obige ist der detaillierte Inhalt vonEntwurfsmuster für umfangreiche JavaScript-Anwendungsarchitekturen (Fortgeschritten). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage