Heim >Web-Frontend >js-Tutorial >Vertiefendes Verständnis der JavaScript-Reihe (22): Detaillierte Erläuterung des Abhängigkeitsinversionsprinzips DIP der fünf Prinzipien von S.O.L.I.D_Grundkenntnisse

Vertiefendes Verständnis der JavaScript-Reihe (22): Detaillierte Erläuterung des Abhängigkeitsinversionsprinzips DIP der fünf Prinzipien von S.O.L.I.D_Grundkenntnisse

WBOY
WBOYOriginal
2016-05-16 16:11:031237Durchsuche

Vorwort

Was wir in diesem Kapitel erklären werden, ist das fünfte der fünf Prinzipien der S.O.L.I.D-JavaScript-Sprachimplementierung, das Dependency Inversion Principle LSP (The Dependency Inversion Principle).

Englischer Originaltext:http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
Abhängigkeitsinversionsprinzip

Die Beschreibung des Abhängigkeitsinversionsprinzips lautet:

A. High-Level-Module sollten nicht von Low-Level-Modulen abhängen.
High-Level-Module sollten nicht von Low-Level-Modulen abhängen, beide sollten von Abstraktionen abhängen

B. Abstraktionen sollten nicht von Details abhängen.
Abstraktion sollte nicht von Details abhängen, Details sollten von Abstraktion abhängen
Das wichtigste Problem beim Abhängigkeitsinversionsprinzip besteht darin, sicherzustellen, dass die Hauptkomponenten einer Anwendung oder eines Frameworks von unwichtigen Komponentenimplementierungsdetails auf niedriger Ebene entkoppelt werden. Dadurch wird sichergestellt, dass die wichtigsten Teile des Programms nicht von Änderungen betroffen sind in Low-Level-Komponenten.

Der erste Teil dieses Prinzips betrifft die Kopplungsmethode zwischen High-Level-Modulen und Low-Level-Modulen. In der traditionellen Split-Architektur hängen High-Level-Module (die die Kerngeschäftslogik des Programms kapseln) immer von einigen Low-Level-Modulen ab -Level-Module (einige grundlegende Punkte). Bei Anwendung des Abhängigkeitsinversionsprinzips kehrt sich das Verhältnis um. Im Gegensatz zu High-Level-Modulen, die von Low-Level-Modulen abhängen, führt die Abhängigkeitsumkehr dazu, dass Low-Level-Module von Schnittstellen abhängig sind, die in High-Level-Modulen definiert sind. Wenn Sie beispielsweise Daten für ein Programm beibehalten möchten, hängt das Kernmodul traditionell von der API eines Persistenzmoduls ab. Nach der Rekonstruktion gemäß dem Abhängigkeitsinversionsprinzip muss das Kernmodul die Persistenz-API-Schnittstelle definieren. und dann muss die Persistenzimplementierungsinstanz diese vom Kernmodul definierte API-Schnittstelle implementieren.

Der zweite Teil des Prinzips beschreibt die richtige Beziehung zwischen Abstraktion und Detail. Um diesen Teil zu verstehen, ist es hilfreicher, die Sprache C zu verstehen, da ihre Anwendbarkeit offensichtlicher ist.

Im Gegensatz zu einigen statisch typisierten Sprachen bietet C kein Konzept auf Sprachebene zum Definieren von Schnittstellen. Welche Beziehung besteht zwischen Klassendefinition und Klassenimplementierung? Klassenmitgliedsmethoden und -variablen, die die Quelldatei implementieren muss. Da alle Variablen und privaten Methoden in Header-Dateien definiert sind, können sie zum Abstrahieren von Implementierungsdetails verwendet werden. Es wird nur durch die Definition abstrakter Methoden (abstrakte Basisklasse in C) implementiert. Das Konzept der Schnittstelle wird zur Implementierung von Klassen verwendet.

DIP und JavaScript

Da JavaScript eine dynamische Sprache ist, ist für die Entkopplung keine Abstraktion erforderlich. Die Änderung, dass Abstraktionen nicht von Details abhängen sollten, hat also keine große Auswirkung auf JavaScript, aber es hat eine große Auswirkung darauf, dass High-Level-Module nicht von Low-Level-Modulen abhängen sollten.

Bei der Erörterung des Abhängigkeitsinversionsprinzips im Kontext statisch typisierter Sprachen umfasst das Konzept der Kopplung semantische und physikalische. Das heißt, wenn ein High-Level-Modul von einem Low-Level-Modul abhängt, koppelt es nicht nur die semantische Schnittstelle, sondern auch die im Low-Level-Modul definierte physische Schnittstelle. Mit anderen Worten: High-Level-Module müssen nicht nur von Bibliotheken Dritter, sondern auch von nativen Low-Level-Modulen entkoppelt werden.

Um dies zu erklären, stellen Sie sich vor, ein .NET-Programm könnte ein sehr nützliches High-Level-Modul enthalten, das von einem Low-Level-Persistenzmodul abhängt. Wenn der Autor der Persistenz-API eine ähnliche Schnittstelle hinzufügen muss, kann das High-Level-Modul unabhängig davon, ob das Prinzip der Abhängigkeitsumkehr verwendet wird oder nicht, nicht in anderen Programmen wiederverwendet werden, ohne die neue Schnittstelle des Low-Level-Moduls erneut zu implementieren.

In JavaScript ist die Anwendbarkeit des Abhängigkeitsinversionsprinzips auf die semantische Kopplung zwischen High-Level-Modulen und Low-Level-Modulen beschränkt. Beispielsweise kann DIP nach Bedarf Schnittstellen hinzufügen, anstatt die durch Low-Level definierten impliziten Schnittstellen zu koppeln Module.

Um dies zu verstehen, schauen wir uns das folgende Beispiel an:

Code kopieren Der Code lautet wie folgt:

$.fn.trackMap = function(options) {
    var defaults = {
        /* Standardwerte */
    };
    Optionen = $.extend({}, Standardeinstellungen, Optionen);

    var mapOptions = {
        Mitte: neues google.maps.LatLng(options.latitude,options.longitude),
        Zoom: 12,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    },
        map = new google.maps.Map(this[0], mapOptions),
        pos = new google.maps.LatLng(options.latitude,options.longitude);

    var marker = new google.maps.Marker({
        Position: pos,
        Titel: Optionen.Titel,
        Symbol: options.icon
    });

    marker.setMap(map);

    options.feed.update(function(latitude, longitude) {
        marker.setMap(null);
        var newLatLng = new google.maps.LatLng(latitude, longitude);
        marker.position = newLatLng;
        marker.setMap(map);
        map.setCenter(newLatLng);
    });

    gib dies zurück;
};

var updater = (function() {
    // private Grundstücke

    zurück {
        Update: Funktion(Rückruf) {
            updateMap = Rückruf;
        }
    };
})();

$("#map_canvas").trackMap({
    Breitengrad: 35.044640193770725,
    Längengrad: -89.98193264007568,
    Symbol: 'http://bit.ly/zjnGDe',
    Titel: 'Tracking-Nummer: 12345',
    Feed: Updater
});

在上述代码里,有个小型的JS类库将一个DIV转化成Map以便显示当前跟踪的位置信息.trackMap函数有2个依赖: Verwenden Sie die Google Maps API und den Standort-Feed职责是当icon位置更新的时候调用一个callback回调(在初始化的时候提供的)并且传入纬度latitude和精度long itude。Google Maps API是用来渲染界面的。

Feed,着重在简单的不同实现, 不需要和Google Maps这么依赖.介于trackMap语义上耦合了Google Maps API, 如果需要切换不同的地图提供商的话那就不得不对trackMap函数进行重写以便可以适配不同的provider.

为了将于Google Maps类库的语义耦合翻转过来,我们需要重写设计trackMap函数,以便对一个隐式接口(抽象出地图提供商provider的接口)进行语义耦合,我们还需要一个适配Google Maps API的一个实现对象,如下是重构后的trackMap函数:

复制代码 代码如下:

$.fn.trackMap = function(options) {
var defaults = {
          /* Standardwerte */
};

Optionen = $.extend({}, Standardeinstellungen, Optionen);

options.provider.showMap(
Dies[0],
options.latitude,
options.longitude,
options.icon,
options.title);

options.feed.update(function(latitude, longitude) {
options.provider.updateMap(Breitengrad, Längengrad);
});

gib dies zurück;
};

$("#map_canvas").trackMap({
Breitengrad: 35.044640193770725,
Längengrad: -89.98193264007568,
Symbol: 'http://bit.ly/zjnGDe',
Titel: „Tracking-Nummer: 12345“,
Feed: Updater,
Anbieter: trackMap.googleMapsProvider
});


In dieser Version haben wir die trackMap-Funktion und die erforderliche Kartenanbieterschnittstelle neu gestaltet und dann die Implementierungsdetails in eine separate googleMapsProvider-Komponente verschoben, die unabhängig in ein separates JavaScript-Modul gepackt werden kann. Das Folgende ist meine googleMapsProvider-Implementierung:
Code kopieren Der Code lautet wie folgt:

trackMap.googleMapsProvider = (function() {
Var-Markierung, Karte;

zurück {
showMap: Funktion(Element, Breitengrad, Längengrad, Symbol, Titel) {
            var mapOptions = {
Mitte: neues google.maps.LatLng(Breitengrad, Längengrad),
Zoom: 12,
              mapTypeId: google.maps.MapTypeId.ROADMAP
            },
pos = new google.maps.LatLng(latitude, longitude);

map = new google.maps.Map(element, mapOptions);

marker = new google.maps.Marker({
Position: pos,
                   Titel: Titel,
Symbol: Symbol
            });

marker.setMap(map);
},
​​​​ updateMap: Funktion(Breitengrad, Längengrad) {
            marker.setMap(null);
            var newLatLng = new google.maps.LatLng(latitude,longitude);
            marker.position = newLatLng;
            marker.setMap(map);
             map.setCenter(newLatLng);
}
};
})();


Nach den oben genannten Änderungen wird die TrackMap-Funktion sehr flexibel und muss nicht auf die Google Maps-API angewiesen sein. Im Gegenteil, sie kann andere Kartenanbieter nach Belieben ersetzen, was bedeutet, dass sie sich entsprechend an jeden Kartenanbieter anpassen kann die Bedürfnisse des Programms.

Wann kommt es zur Abhängigkeitsinjektion?

Etwas irrelevant. Tatsächlich wird das Konzept der Abhängigkeitsinjektion oft mit dem Prinzip der Abhängigkeitsinversion verwechselt. Um diesen Unterschied zu verdeutlichen, müssen wir Folgendes erklären:

Abhängigkeitsinjektion ist eine spezielle Form der Kontrollinversion, also die Art und Weise, wie eine Komponente ihre Abhängigkeiten erhält. Abhängigkeitsinjektion bedeutet, dass Abhängigkeiten für Komponenten bereitgestellt werden, anstatt dass Komponenten Abhängigkeiten erhalten. Dies bedeutet, dass eine Instanz einer Abhängigkeit erstellt, die Abhängigkeit über die Factory angefordert wird und die Abhängigkeit über den Service Locator oder die Initialisierung der Komponente selbst angefordert wird. Das Dependency-Inversion-Prinzip und die Dependency-Injection konzentrieren sich beide auf Abhängigkeiten und werden zur Inversion verwendet. Das Abhängigkeitsinversionsprinzip konzentriert sich jedoch nicht darauf, wie Komponenten Abhängigkeiten erhalten, sondern nur darauf, wie High-Level-Module von Low-Level-Modulen entkoppelt werden. In gewissem Sinne ist das Abhängigkeitsinversionsprinzip eine andere Form der Kontrollinversion. Hier wird umgekehrt, welches Modul die Schnittstelle definiert (von der Low-Level-Definition zur High-Level-Definition).

Zusammenfassung

Dies ist der letzte Artikel der fünf Prinzipien. In diesen fünf Artikeln haben wir gesehen, wie SOLID in JavaScript implementiert wird. Verschiedene Prinzipien werden in JavaScript erläutert. (Anmerkung des Onkels: Tatsächlich habe ich das Gefühl, dass die allgemeinen Prinzipien in verschiedenen Sprachen tatsächlich die gleichen sind, obwohl es etwas unscheinbar ist.)

Stellungnahme:
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