Une brève note sur les modèles de conception - le principe d'inversion de dépendance du principe de conception

3.5 Principe d'inversion de dépendance

3.5.1 Inversion de contrôle (IOC)

  • Inversion Of Control, abrégé en IOC
public abstract class TestCase {
  public void run() {
    if (doTest()) {
      System.out.println("Test succeed.");
    } else {
      System.out.println("Test failed.");
    }
  }
  
  public abstract boolean doTest();
}

public class JunitApplication {
  private static final List<TestCase> testCases = new ArrayList<>();
  
  public static void register(TestCase testCase) {
    testCases.add(testCase);
  }
  
  public static final void main(String[] args) {
    for (TestCase case: testCases) {
      case.run();
    }
  }

Après avoir introduit cette version simplifiée du framework de test dans le projet, il vous suffit de remplir le code de test spécifique dans le point d'extension réservé par le framework, c'est-à-dire la fonction abstraite doTest () dans la classe TestCase. Il n'est pas nécessaire d'écrire la fonction main () responsable de l'exécution du processus. Le code spécifique est le suivant:

public class UserServiceTest extends TestCase {
  @Override
  public boolean doTest() {
    // ... 
  }
}

// 注册操作还可以通过配置的方式来实现,不需要程序员显示调用register()
JunitApplication.register(new UserServiceTest();
  • Il s'agit d'un exemple typique de mise en œuvre de «l'inversion de contrôle» via un framework: le framework fournit un squelette de code extensible pour assembler des objets et gérer l'ensemble du processus d'exécution. Lorsque les programmeurs utilisent le framework pour le développement, ils n'ont qu'à ajouter du code lié à leur entreprise au point d'extension réservé, et ils peuvent utiliser le framework pour piloter l'exécution de l'ensemble du processus du programme.

  • "Contrôle" se réfère au contrôle du flux d'exécution du programme, et "inverse" se réfère au propre contrôle du programmeur de l'exécution de l'ensemble du programme avant l'utilisation du framework. Après avoir utilisé le framework, le flux d'exécution de l'ensemble du programme peut être contrôlé par le framework. Contrôle du processus "inversé" du programmeur vers le framework.

  • L'inversion de contrôle n'est pas une technique de mise en œuvre spécifique, mais une idée de conception plus générale, généralement utilisée pour guider la conception du niveau du cadre.

3.5.2 Injection de dépendance (DI)

  • Injection de dépendance, en abrégé DI

  • Contrairement à l'inversion de contrôle, il s'agit d'une technique de codage spécifique

  • Pour résumer en une phrase: au lieu de créer un objet de classe dépendante à l'intérieur de la classe via new (), mais après avoir créé l'objet de classe dépendante en externe, passez (ou injectez) à la classe via le constructeur, les paramètres de fonction, etc.

  • Exemple: la classe Notification est responsable de l'envoi de messages et s'appuie sur la classe MessageSender pour envoyer des messages tels que des promotions de produits et des codes de vérification aux utilisateurs. Utilisez l'injection de dépendance et l'injection de non-dépendance pour y parvenir. Le code d'implémentation spécifique est le suivant:

    // 非依赖注入实现方式
    public class Notification {
      private MessageSender messageSender;
      
      public Notification() {
        this.messageSender = new MessageSender(); //此处有点像hardcode
      }
      
      public void sendMessage(String cellphone, String message) {
        //...省略校验逻辑等...
        this.messageSender.send(cellphone, message);
      }
    }
    
    public class MessageSender {
      public void send(String cellphone, String message) {
        //....
      }
    }
    // 使用Notification
    Notification notification = new Notification();
    
    // 依赖注入的实现方式
    public class Notification {
      private MessageSender messageSender;
      
      // 通过构造函数将messageSender传递进来
      public Notification(MessageSender messageSender) {
        this.messageSender = messageSender;
      }
      
      public void sendMessage(String cellphone, String message) {
        //...省略校验逻辑等...
        this.messageSender.send(cellphone, message);
      }
    }
    //使用Notification
    MessageSender messageSender = new MessageSender();
    Notification notification = new Notification(messageSender);
    

    Optimisation:

    public class Notification {
      private MessageSender messageSender;
      
      public Notification(MessageSender messageSender) {
        this.messageSender = messageSender;
      }
      
      public void sendMessage(String cellphone, String message) {
        this.messageSender.send(cellphone, message);
      }
    }
    
    public interface MessageSender {
      void send(String cellphone, String message);
    }
    
    // 短信发送类
    public class SmsSender implements MessageSender {
      @Override
      public void send(String cellphone, String message) {
        //....
      }
    }
    
    // 站内信发送类
    public class InboxSender implements MessageSender {
      @Override
      public void send(String cellphone, String message) {
        //....
      }
    }
    
    //使用Notification
    MessageSender messageSender = new SmsSender();
    Notification notification = new Notification(messageSender);
    

    Dans ce qui précède, les objets de classe dépendants sont transmis via l'injection de dépendances, qui peut remplacer de manière flexible les classes dépendantes et améliorer l'évolutivité du code .

3.5.3 Cadre d'injection de dépendance (cadre DI)

  • Il existe de nombreux frameworks d'injection de dépendances, tels que Google Guice, Java Spring, Pico Container, Butterfly Container, etc.
  • Il vous suffit de configurer tous les objets de classe à créer, les dépendances entre les classes et les classes via les points d'extension fournis par le framework d'injection de dépendances, et vous pouvez implémenter le framework pour créer automatiquement des objets, gérer le cycle de vie des objets et l'injection de dépendances. Des choses qui nécessitent des programmeurs.

3.5.4 Principe d'inversion de dépendance (DIP)

  • Principe d'inversion de dépendance, abrégé en DIP

  • Les modules de haut niveau ne dépendent pas des modules de bas niveau. Les modules de haut niveau et les modules de bas niveau doivent s'appuyer les uns sur les autres par le biais d'abstractions.

  • L'abstraction (abstractions) ne repose pas sur des détails d'implémentation spécifiques (détails), les détails d'implémentation spécifiques (détails) dépendent de l'abstraction (abstractions).

  • La division des modules de haut niveau et des modules de bas niveau est simplement que, dans la chaîne d'appel, l'appelant appartient au niveau supérieur et l'appelé appartient au niveau inférieur.

  • Exemple: Tomcat est un conteneur pour exécuter des applications Web Java. Le code d'application Web que nous écrivons doit uniquement être déployé sous le conteneur Tomcat, puis il peut être appelé et exécuté par le conteneur Tomcat. Selon le principe de division précédent, Tomcat est un module de haut niveau et le code d'application Web que nous écrivons est un module de bas niveau. Il n'y a pas de dépendance directe entre Tomcat et le code d'application. Les deux s'appuient sur la même "abstraction", qui est la spécification Servlet. La spécification Servlet ne dépend pas des détails d'implémentation de conteneurs et d'applications Tomcat spécifiques, tandis que le conteneur et les applications Tomcat dépendent de la spécification Servlet.

3.5.5 avis

  • SmallFly:

    Le concept du principe d'inversion de dépendance est que les modules de haut niveau ne dépendent pas de modules de bas niveau. Il semble que des modules de haut niveau soient nécessaires, mais cela réglemente en fait la conception des modules de bas niveau.

    L'interface fournie par le module de bas niveau doit être suffisamment abstraite et générale, et le type d'utilisation et le scénario du module de haut niveau doivent être pris en compte lors de la conception .

    De toute évidence, le module de haut niveau doit utiliser le module de bas niveau et dépendre du module de bas niveau. Au contraire, les modules de bas niveau doivent être conçus selon des modules de haut niveau, et l'apparition de "inversé" apparaît .

    Cette conception présente deux avantages:

    1. Les modules de bas niveau sont plus polyvalents et plus applicables
    2. Le module de haut niveau ne dépend pas de la mise en œuvre spécifique du module de bas niveau, ce qui facilite le remplacement du module de bas niveau

Je suppose que tu aimes

Origine www.cnblogs.com/wod-Y/p/12746794.html
conseillé
Classement