Maison >interface Web >js tutoriel >Compréhension approfondie de la série JavaScript (22) : Explication détaillée du principe d'inversion de dépendance DIP des cinq principes de S.O.L.I.D_Basic Knowledge

Compréhension approfondie de la série JavaScript (22) : Explication détaillée du principe d'inversion de dépendance DIP des cinq principes de S.O.L.I.D_Basic Knowledge

WBOY
WBOYoriginal
2016-05-16 16:11:031242parcourir

Avant-propos

Ce que nous allons expliquer dans ce chapitre est le cinquième des cinq principes d'implémentation du langage JavaScript S.O.L.I.D, le principe d'inversion de dépendance LSP (The Dependency Inversion Principe).

Texte original en anglais :http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
Principe d'inversion de dépendance

La description du principe d'inversion de dépendance est :

A. Les modules de haut niveau ne devraient pas dépendre de modules de bas niveau.
Les modules de haut niveau ne doivent pas dépendre de modules de bas niveau, les deux doivent dépendre d'abstractions

B. Les abstractions ne devraient pas dépendre des détails.
L'abstraction ne devrait pas dépendre des détails, les détails devraient dépendre de l'abstraction
Le problème le plus important avec le principe d'inversion de dépendance est de garantir que les principaux composants d'une application ou d'un framework sont découplés des détails d'implémentation des composants de bas niveau non importants. Cela garantira que les parties les plus importantes du programme ne sont pas affectées par les changements. dans les composants de bas niveau.

La première partie de ce principe concerne la méthode de couplage entre les modules de haut niveau et les modules de bas niveau. Dans l'architecture divisée traditionnelle, les modules de haut niveau (encapsulant la logique métier de base du programme) dépendent toujours de certains éléments de bas niveau. modules de niveau (quelques points de base). Lorsqu’on applique le principe d’inversion de dépendance, la relation est inversée. Contrairement aux modules de haut niveau qui dépendent de modules de bas niveau, l'inversion de dépendances fait dépendre les modules de bas niveau des interfaces définies dans les modules de haut niveau. Par exemple, si vous souhaitez conserver les données d'un programme, la conception traditionnelle est que le module principal dépend de l'API d'un module de persistance. Après reconstruction selon le principe d'inversion de dépendance, le module principal doit définir l'interface API de persistance, puis l'instance d'implémentation de persistance doit implémenter cette interface API définie par le module principal.

La deuxième partie du principe décrit la relation correcte entre abstraction et détail. Pour comprendre cette partie, il est plus utile de comprendre le langage C, car son applicabilité est plus évidente.

Contrairement à certains langages typés statiquement, C ne fournit pas de concept au niveau du langage pour définir les interfaces. Quelle est la relation entre la définition de classe et l'implémentation de classe ? En C, les classes sont définies sous la forme de fichiers d'en-tête. méthodes et variables membres de la classe que le fichier source doit implémenter. Étant donné que toutes les variables et méthodes privées sont définies dans les fichiers d'en-tête, elles peuvent être utilisées pour extraire les détails de l'implémentation. Il est implémenté en définissant uniquement des méthodes abstraites (classe de base abstraite en C). La notion d'interface est utilisée pour implémenter des classes.

DIP et JavaScript

JavaScript étant un langage dynamique, il n'est pas nécessaire de faire de l'abstraction pour le découplage. Ainsi, le changement selon lequel les abstractions ne doivent pas dépendre des détails n'a pas un grand impact sur JavaScript, mais il a un grand impact sur le fait que les modules de haut niveau ne doivent pas dépendre des modules de bas niveau.

Lorsque l'on discute du principe d'inversion de dépendance dans le contexte des langages typés statiquement, le concept de couplage inclut le sémantique et le physique. C'est-à-dire que si un module de haut niveau dépend d'un module de bas niveau, il couple non seulement l'interface sémantique, mais aussi l'interface physique définie dans le module de bas niveau. Autrement dit, les modules de haut niveau doivent non seulement être découplés des bibliothèques tierces, mais également des modules natifs de bas niveau.

Pour expliquer cela, imaginez qu'un programme .NET puisse contenir un module de haut niveau très utile qui dépend d'un module de persistance de bas niveau. Lorsque l'auteur a besoin d'ajouter une interface similaire à l'API de persistance, que le principe d'inversion de dépendance soit utilisé ou non, le module de haut niveau ne peut pas être réutilisé dans d'autres programmes sans réimplémenter la nouvelle interface du module de bas niveau.

En JavaScript, l'applicabilité du principe d'inversion de dépendance est limitée au couplage sémantique entre les modules de haut niveau et les modules de bas niveau. Par exemple, DIP peut ajouter des interfaces selon les besoins au lieu de coupler les interfaces implicites définies par les modules de bas niveau. modules.

Pour comprendre cela, regardons l'exemple suivant :

Copier le code Le code est le suivant :

$.fn.trackMap = fonction (options) {
    var valeurs par défaut = {
        /* valeurs par défaut */
    };
    options = $.extend({}, valeurs par défaut, options);

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

    var marqueur = nouveau google.maps.Marker({
        poste : pos,
        titre : options.titre,
        icône : options.icon
    });

    Marker.setMap(map);

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

    retournez ceci ;
};

var updater = (function() {
    // propriétés privées

    revenir {
        mise à jour : fonction (rappel) {
            updateMap = rappel;
        >
    };
})();

$("#map_canvas").trackMap({
    latitude: 35.044640193770725,
    longitude: -89.98193264007568,
    icône : 'http://bit.ly/zjnGDe',
    titre : 'Numéro de suivi : 12345',
    flux : programme de mise à jour
});

在上述代码里,有个小型的JS类库将一个DIV转化成Map以便显示当前跟踪的位置信息。trackMap函数有2个依赖:第三方的API Google Maps et flux de localisation. Icône d'icône de rappel pour rappel (latitude et longitude) 。API Google Maps是用来渲染界面的。

feed对象的接口可能按照装,也可能没有照装trackMap函数的要求去设计,事实上,他的角色很简单,着Il s'agit d'un exemple de Google Maps. Il s'agit de l'API Google Maps et de l'API trackMap.以适配不同的fournisseur。

Les cartes Google Maps sont également disponibles pour trackMap et trackMap.象出地图提供商provider的接口)进行语义耦合,我们还需要一个适配L'API Google Maps est une application de suivi de trackMap :

复制代码 代码如下 :

$.fn.trackMap = fonction (options) {
var valeurs par défaut = {
          /* valeurs par défaut */
};

options = $.extend({}, valeurs par défaut, options);

options.provider.showMap(
Ceci[0],
options.latitude,
options.longitude,
options.icône,
options.title);

options.feed.update(function(latitude, longitude) {
options.provider.updateMap(latitude, longitude);
});

retourne ceci ;
};

$("#map_canvas").trackMap({
Latitude : 35.044640193770725,
Longitude : -89.98193264007568,
icône : 'http://bit.ly/zjnGDe',
Titre : « Numéro de suivi : 12345 »,
Flux : mise à jour,
Fournisseur : trackMap.googleMapsProvider
});


Dans cette version, nous avons repensé la fonction trackMap et l'interface du fournisseur de cartes requise, puis avons déplacé les détails d'implémentation vers un composant googleMapsProvider distinct, qui peut être intégré indépendamment dans un module JavaScript distinct. Voici mon implémentation de googleMapsProvider :
Copier le code Le code est le suivant :

trackMap.googleMapsProvider = (function() {
marqueur var, carte ;

revenir {
showMap : fonction (élément, latitude, longitude, icône, titre) {
            var mapOptions = {
centre : nouveau google.maps.LatLng(latitude, longitude),
zoom : 12,
              mapTypeId : google.maps.MapTypeId.ROADMAP
            },
pos = nouveau google.maps.LatLng(latitude, longitude);

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

marqueur = nouveau google.maps.Marker({
poste : pos,
                   titre : titre,
icône : icône
            });

marker.setMap(map);
},
​​​​ updateMap : fonction (latitude, longitude) {
            Marker.setMap(null);
            var newLatLng = new google.maps.LatLng(latitude,longitude);
            Marker.position = newLatLng;
            Marker.setMap(map);
             map.setCenter(newLatLng);
>
};
})();


Après avoir apporté les modifications ci-dessus, la fonction trackMap deviendra très flexible et ne devra pas s'appuyer sur l'API Google Maps. Au contraire, elle pourra remplacer à volonté d'autres fournisseurs de cartes, ce qui signifie qu'elle pourra s'adapter à n'importe quel fournisseur de cartes selon ses besoins. les besoins du programme.

Quand a lieu l'injection de dépendance ?

Un peu hors de propos. En fait, la notion d'injection de dépendances est souvent confondue avec le principe d'inversion de dépendances. Afin de clarifier cette différence, il faut expliquer :

L'injection de dépendances est une forme spéciale d'inversion de contrôle, c'est-à-dire la manière dont un composant obtient ses dépendances. L'injection de dépendances signifie que les dépendances sont fournies aux composants, plutôt que les composants n'obtiennent des dépendances, cela signifie créer une instance d'une dépendance, demander la dépendance via l'usine et demander la dépendance via le localisateur de services ou l'initialisation du composant lui-même. Le principe d'inversion de dépendances et l'injection de dépendances se concentrent tous deux sur les dépendances et sont utilisés pour l'inversion. Cependant, le principe d'inversion des dépendances ne se concentre pas sur la manière dont les composants obtiennent des dépendances, mais uniquement sur la façon dont les modules de haut niveau sont découplés des modules de bas niveau. Dans un sens, le principe d'inversion de dépendance est une autre forme d'inversion de contrôle. Ce qui est inversé ici, c'est quel module définit l'interface (de la définition de bas niveau à la définition de haut niveau).

Résumé

Ceci est le dernier article des cinq principes. Dans ces cinq articles, nous avons vu comment SOLID est implémenté en JavaScript. Différents principes sont expliqués en JavaScript sous différents angles. (Note de l'oncle : En fait, j'ai l'impression que même si c'est un peu quelconque, à un autre niveau, les principes généraux sont en fait les mêmes dans différentes langues.)

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn