Modèles de conception - Introduction aux modèles de conception et au modèle de conception singleton

 la navigation: 

[Notes Java de Dark Horse + Résumé de la marche sur la fosse] JavaSE+JavaWeb+SSM+SpringBoot+Riji Takeaway+SpringCloud+Dark Horse Tourism+Guli Mall+Xuecheng Online+Design Mode+Nioke Interview Questions

 

Table des matières  

1. Présentation et classification des modèles de conception

1.1 Introduction aux modèles de conception

1.2 Classification des modèles de conception

2. Modèle de conception de création - modèle singleton

2.1 Présentation

2.2 Comment créer huit motifs singleton

2.2.1 Style affamé (constante statique)

2.2.2 Style affamé (bloc de code statique)

2.2.3 Style paresseux (thread non sécurisé)

2.2.4 Style paresseux (thread-safe, méthodes synchronisées)

2.2.5 Style paresseux (thread non sécurisé, blocs de code synchronisés)

2.2.6 Double vérification (recommandé, thread-safe, chargement différé)

2.2.7 Classe interne statique (recommandé)

2.2.8 Énumération (recommandée)

2.2.9 Analyse du mode singleton dans le code source du JDK


1. Présentation et classification des modèles de conception

1.1 Introduction aux modèles de conception

  • 1) Le modèle de conception est l'expérience utile résumée par les programmeurs face à des problèmes de conception d'ingénierie logicielle similaires. Les modèles ne sont pas des codes, mais des solutions générales à certains types de problèmes , et les modèles de conception représentent les meilleures pratiques. Ces solutions sont le résultat d'essais et d'erreurs par de nombreux développeurs de logiciels sur une période de temps considérable
  • 2) L'essence du modèle de conception améliore la maintenabilité, la polyvalence et l'évolutivité du logiciel , et réduit la complexité du logiciel
  • 3) "Design Patterns" est un livre classique écrit par Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides Design (communément appelé "Group of Four GOF")
  • 4) Les modèles de conception ne sont pas limités à un certain langage, Java, PHP et C++ ont tous des modèles de conception

1.2 Classification des modèles de conception

Dans les modèles de conception, il est généralement divisé en trois types de modèles de conception, qui sont les modèles de création, les modèles structurels et les modèles de comportement.

  • Modèles de création : principalement utilisés pour la création d'objets , y compris plusieurs modèles différents, tels que le modèle de méthode d'usine, le modèle d'usine abstrait, le modèle de générateur, le modèle singleton et le modèle de prototype. Ces modèles aident à réduire le couplage du système et à améliorer la réutilisabilité et l'évolutivité du code.

  • Modèles structurels : principalement utilisés pour décrire la relation de combinaison entre les objets , y compris plusieurs modèles différents, tels que "modèle proxy", "modèle adaptateur", "modèle pont", "modèle décorateur", "mode apparence", "mode poids mouche" et "mode combiné", etc. Ces modèles peuvent nous aider à mieux concevoir la structure du programme et à améliorer la flexibilité et la maintenabilité du code.

  • Modèles de comportement : principalement utilisés pour décrire la communication et l'attribution des responsabilités entre les objets , y compris plusieurs modèles différents, tels que "modèle de stratégie", "modèle de méthode de modèle", "modèle d'observateur", "modèle d'itérateur", "mode chaîne de responsabilité", " Mode Commande", "Mode Visiteur", "Mode Mémo" et "Mode Interprète", etc. Ces modèles sont souvent utilisés pour implémenter différents algorithmes, processus et méthodes de communication afin d'obtenir une plus grande flexibilité et maintenabilité du système.

Il existe trois types de modèles de conception

  • Patterns créationnels : pattern singleton, pattern abstract factory, pattern prototype, pattern builder, pattern factory
  • Motifs structurels : Motif adaptateur, Motif pont, Motif décoration , Motif composite, Motif apparence, Motif poids mouche, Motif proxy
  • Modèles de comportement : modèle de méthode , modèle de commande, modèle de visiteur, modèle d'itérateur, modèle d'observateur, modèle d'intermédiaire, modèle de mémo, modèle d'interprète (modèle d'interprète), modèle d'état, modèle de stratégie, modèle de chaîne de responsabilité (modèle de chaîne de responsabilité)

Remarque : il existe de légères différences de classification et de noms dans différents livres

2. Modèle de conception de création - modèle singleton

2.1 Présentation

Le soi-disant modèle de conception singleton d'une classe consiste à adopter une certaine méthode pour garantir que dans l'ensemble du système logiciel, il ne peut y avoir qu'une seule instance d'objet pour une certaine classe , et cette classe ne fournit qu'une méthode (méthode statique) pour obtenir son instance d'objet.

Comme SessionFactory d'Hibernate, qui agit comme un proxy pour les sources de stockage de données et est responsable de la création d'objets Session. SessionFactory n'est pas léger. En général, un projet n'a généralement besoin que d'une seule SessionFactory , qui utilisera le mode singleton

avantage:

  • Économie de ressources : il n'y a qu'une seule instance du modèle singleton, ce qui peut éviter la création répétée d'objets , économisant ainsi des ressources et améliorant les performances du système.
  • Gérer les variables globales : le modèle singleton peut être utilisé pour gérer l'état global et les variables afin de faciliter le partage de données dans l'ensemble du système .
  • Simplifier l'architecture du système : l'utilisation du modèle singleton peut simplifier l'architecture du système, réduire le nombre de classes et la complexité de l'interface.

défaut:

  1. Peut causer des problèmes de simultanéité : lorsque le mode singleton est utilisé en multithreading, il doit garantir la sécurité des threads, sinon cela peut entraîner des problèmes de simultanéité.
  2. Peut augmenter la complexité du système : une utilisation excessive du modèle singleton peut augmenter la complexité du système, ce qui rend le code difficile à maintenir.
  3. Difficile à déboguer : en raison de l'état partagé global du mode singleton, il peut entraîner des problèmes lors du débogage qui sont difficiles à localiser et à tester.

 Précautions et scénarios d'utilisation

  • 1) Le mode singleton garantit qu'un seul objet de cette classe existe dans la mémoire système, ce qui permet d'économiser les ressources système . Pour certains objets qui doivent être créés et détruits fréquemment, l'utilisation du mode singleton peut améliorer les performances du système
  • 2) Lorsque vous souhaitez instancier une classe singleton, vous devez vous rappeler d'utiliser la méthode correspondante d'obtention de l'objet au lieu d'utiliser new
  • 3) Scénarios pour le mode singleton : objets qui doivent être créés et détruits fréquemment, objets qui prennent trop de temps pour créer ou consomment trop de ressources mais qui sont souvent utilisés (par exemple : objets lourds), objets outils, objets qui accèdent fréquemment aux bases de données ou fichiers (tels que des sources de données, des usines de session, etc.)

2.2 Comment créer huit motifs singleton

  • 1) Style chinois affamé (constante statique) : thread-safe, la mémoire sera gaspillée si elle n'est pas utilisée.
  • 2) Style chinois affamé (bloc de code statique) : thread-safe, il gaspillera de la mémoire s'il n'est pas utilisé.
  • 3) Style paresseux (thread non sécurisé) : chargement paresseux, thread non sécurisé. Autrement dit, instanciez-le lorsqu'il est utilisé, et plusieurs instances peuvent être créées en cas de multithread. Ne l'utilisez pas de cette façon.
  • 4) Style paresseux (sécurité des threads, méthode de synchronisation) : sécurité des threads, mais faible efficacité (verrouillage à chaque fois qu'une instance est acquise), déconseillé.
  • 5) Style paresseux (les threads ne sont pas sûrs, blocs de code synchronisés) : les threads ne sont pas sûrs, n'utilisez pas cette méthode.
  • 6) Vérifiez
  • 7) Classe interne statique
  • 8) Énumération

2.2.1 Style affamé (constante statique)

Thread-safe, il gaspillera de la mémoire s'il n'est pas utilisé.

marcher:

  1. Privatisation du constructeur (pour empêcher le neuf externe)
  2. Créer un objet constant statique privé à l'intérieur de la classe
  3. Exposer une méthode publique statique getInstance

public class Singleton {
    // 1、构造器私有化
    private Singleton() {
    }

    // 2、类的内部创建对象
    private static final Singleton instance = new Singleton();

    // 3、向外暴露一个静态的公共方法
    public static Singleton getInstance() {
        return instance;
    }
}

Avantages et inconvénients

  • Avantages : Ce mode d'écriture est relativement simple, c'est-à-dire que l'instanciation est terminée au chargement de la classe (les variables de classe seront affectées lors des phases de préparation et d'initialisation du chargement de la classe JVM). Évite les problèmes de synchronisation des threads
  • Inconvénient : l'instanciation est terminée lorsque la classe est chargée, ce qui n'atteint pas l'effet de Lazy Loading . Si cette instance n'est jamais utilisée du début à la fin, cela entraînera un gaspillage de mémoire.
  • Cette méthode évite les problèmes de synchronisation multi-thread basés sur le mécanisme de classloder. Cependant, l'instance est instanciée lorsque la classe est chargée, et la plupart du mode singleton appelle la méthode getlnstance, mais il existe de nombreuses raisons pour le chargement de la classe, il n'est donc pas certain qu'il existe d'autres moyens (ou d'autres méthodes statiques) pour provoquer la classe à Loading, à ce moment, l'initialisation de l'instance n'atteint pas l'effet de Lazy loading
  • Conclusion : ce mode singleton est disponible et peut entraîner une perte de mémoire

2.2.2 Style affamé (bloc de code statique)

Thread-safe, il gaspillera de la mémoire s'il n'est pas utilisé.

marcher:

  1. privatisation constructeur
  2. Références d'objets statiques privés déclarés en interne de la classe
  3. Instancier un objet dans un bloc de code statique
  4. Exposer une méthode publique statique

public class Singleton {
    // 1、构造器私有化
    private Singleton() {
    }

    // 2、类的内部声明对象
    private static Singleton instance;

    // 3、在静态代码块中创建对象
    static {
        instance = new Singleton();
    }

    // 4、向外暴露一个静态的公共方法
    public static Singleton getInstance() {
        return instance;
    }
}

Avantages et inconvénients

  • 1) Cette méthode est en fait similaire à la méthode constante statique ci-dessus, sauf que le processus d'instanciation de la classe est placé dans le bloc de code statique , et lorsque la classe est chargée, le code dans le bloc de code statique est exécuté pour initialiser l'instance de la classe. Les avantages et les inconvénients sont les mêmes que ci-dessus.
  • 2) Conclusion : Ce mode singleton est disponible, mais il peut entraîner une perte de mémoire

2.2.3 Style paresseux (thread non sécurisé)

Chargement paresseux, non thread-safe. Autrement dit, instanciez-le lorsqu'il est utilisé, et plusieurs instances peuvent être créées en cas de multithread. Ne l'utilisez pas de cette façon.

marcher:

  1. privatisation constructeur
  2. Créer une référence d'objet statique privée à l'intérieur de la classe
  3. Exposez une méthode statique publique à l'extérieur et ne créez une instance que lorsque cette méthode est utilisée

// 1、构造器私有化
private Singleton() {
}

// 2、类的内部声明对象
private static Singleton instance;

// 3、向外暴露一个静态的公共方法,当使用到该方法时,才去创建 instance
public static Singleton getInstance() {
    if (instance == null) {
        instance = new Singleton();
    }
    return instance;
}

Avantages et inconvénients

  • 1) Il a l'effet du Lazy Loading , mais il ne peut être utilisé que sous un seul thread
  • 2) Si sous multi-threading , un thread entre dans le bloc de déclaration de jugement et qu'un autre thread passe également la déclaration de jugement avant qu'il n'ait le temps de s'exécuter, alors plusieurs instances seront générées
  • 3) Conclusion : En développement réel, n'utilisez pas cette méthode

2.2.4 Style paresseux (thread-safe, méthodes synchronisées)

Thread safe, mais inefficace (verrouillage à chaque fois qu'une instance est acquise), non recommandé.

  • 1) Privatisation constructeur
  • 2) Créer des objets à l'intérieur de la classe
  • 3) Exposez une méthode synchronisée statique publique à l'extérieur et ne créez une instance que lorsque cette méthode est utilisée

public class Singleton {
    // 1、构造器私有化
    private Singleton() {
    }

    // 2、类的内部声明对象
    private static Singleton instance;

    // 3、向外暴露一个静态的公共方法,加入同步处理的代码,解决线程安全问题
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Avantages et inconvénients

  • 1) Résoudre le problème de l'insécurité des threads
  • 2) L'efficacité est trop faible Lorsque chaque thread veut obtenir une instance de la classe, la getlnstance()méthode d'exécution doit être synchronisée. En fait, cette méthode n'exécute qu'une seule fois le code d'instanciation, et si vous souhaitez obtenir une instance de cette classe ultérieurement, vous pouvez simplement returnle faire directement. La méthode de synchronisation est trop inefficace
  • 3) Conclusion : En développement réel, cette méthode n'est pas recommandée

2.2.5 Style paresseux (thread non sécurisé, blocs de code synchronisés)

Le thread n'est pas sûr, n'utilisez pas cette méthode.

  • 1) Privatisation constructeur
  • 2) Créer des objets à l'intérieur de la classe
  • 3) Exposez une méthode publique statique à l'extérieur et ajoutez un bloc de code pour le traitement synchrone

public class Singleton {
    // 1、构造器私有化
    private Singleton() {
    }

    // 2、类的内部声明对象
    private static Singleton instance;

    // 3、向外暴露一个静态的公共方法,加入同步处理的代码,解决线程安全问题
    public static Singleton getInstance() {
        if (instance == null) {    //可能有多个线程同时通过检查,多次执行下面代码,产生多个实例
//类级别的锁对象,锁对象是全局的,对该类的所有实例均有效。回顾锁对象是this时仅限于锁当前实例
            synchronized (Singleton.class) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}

Avantages et inconvénients

  • 1) Cette méthode est destinée à améliorer la quatrième méthode de mise en œuvre, car la méthode de synchronisation précédente est trop inefficace et elle est modifiée pour générer de manière synchrone des blocs de code instanciés
  • 2) Mais cette synchronisation ne joue pas le rôle de synchronisation des threads. Conformément à la situation rencontrée dans la troisième méthode d'implémentation, si un thread entre dans le bloc d'instructions de jugement et n'a pas le temps de l'exécuter à l'avenir, un autre thread passe également l'instruction de jugement et plusieurs instances seront générées à ce moment.
  • 3) Conclusion : En développement réel, cette méthode ne peut pas être utilisée

2.2.6 Double vérification (recommandé, thread-safe, chargement différé)

  1. privatisation constructeur
  2. Les références d'objet sont créées à l'intérieur de la classe et modifiées avec le mot-clé volatile
  3. Exposez une méthode publique statique à l'extérieur, ajoutez des blocs de code de traitement synchrone et effectuez des doubles jugements pour résoudre les problèmes de sécurité des threads

public class Singleton {
    // 1、构造器私有化
    private Singleton() {
    }

    // 2、类的内部声明对象,同时用`volatile`关键字修饰,为了保证可见性。
//原子性、可见性(修改立即更新到内存)、有序性
    private static volatile Singleton instance;

    // 3、向外暴露一个静态的公共方法,加入同步处理的代码块,并进行双重判断,解决线程安全问题
    public static Singleton getInstance() {
        if (instance == null) {    //第一次检查,可能有多个线程同时通过检查
//类级别的锁对象,锁对象是全局的,对该类的所有实例均有效。回顾锁对象是this时仅限于锁当前实例
            synchronized (Singleton.class) {    
                if (instance == null) {   //第二次检查,只会有1个线程通过检查并创建实例
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Avantages et inconvénients

  • 1) Le concept Double-Check est souvent utilisé dans le développement multi-thread. Nous avons vérifié deux fois pour assurer la sécurité des threads
  • 2) De cette façon, le code d'instanciation n'a besoin d'être exécuté qu'une seule fois, et l'objet d'instanciation est renvoyé directement lorsqu'il est à nouveau accédé ultérieurement, et la synchronisation répétée de la méthode est également évitée
  • 3) Sécurité des fils ; chargement paresseux ; plus grande efficacité
  • 4) Conclusion : En développement réel, il est recommandé d'utiliser ce modèle de conception singleton

2.2.7 Classe interne statique (recommandé)

Thread safe, chargement paresseux, haute efficacité, recommandé. 

marcher: 

  • 1) Privatisation constructeur
  • 2) Définir une classe interne statique qui définit en interne les propriétés statiques de la classe actuelle
  • 3) Exposer une méthode publique statique à l'extérieur

Connaissance station-service :

  1. Le mécanisme de chargement de classe est un chargement paresseux, c'est-à-dire qu'il ne sera chargé que lorsqu'une classe est nécessaire.
  2. Pendant le processus de chargement de la classe, tous ses membres statiques seront chargés en mémoire, y compris les variables statiques, les méthodes de membres statiques et les classes internes statiques.
  3. Le chargement de classe comprend le chargement, la liaison (vérification, préparation (allocation de mémoire pour les variables de classe et attribution de valeurs nulles), analyse), l'initialisation (attribution de valeurs initiales aux variables de classe, exécution de blocs d'instructions statiques).
public class Singleton {
    // 1、构造器私有化
    private Singleton() {
    }

    // 2、定义一个静态内部类,内部定义当前类的静态属性
    private static class SingletonInstance {
        private static final Singleton instance = new Singleton();
    }

    // 3、向外暴露一个静态的公共方法
    public static Singleton getInstance() {
        return SingletonInstance.instance;
    }
}

Avantages et inconvénients

  • 1) Cette méthode utilise un mécanisme de chargement de classe pour s'assurer qu'il n'y a qu'un seul thread lors de l'initialisation d'une instance
  • 2) La méthode de classe interne statique n'instancie pas la classe Singleton immédiatement lorsqu'elle est chargée, mais appelle la méthode lorsqu'elle doit être instanciée, puis getlnstancecharge la classe Singletonlnstance, complétant ainsi l'instanciation du Singleton.
  • 3) Les propriétés statiques de la classe ne seront initialisées que lors du premier chargement de la classe. La JVM nous aide à assurer la sécurité du thread . Lorsque la classe est initialisée, les autres threads ne peuvent pas entrer
  • 4) Avantages : évitez l'insécurité des threads, utilisez les caractéristiques statiques de la classe interne pour obtenir un chargement paresseux et une efficacité élevée
  • 5) Conclusion : Il est recommandé d'utiliser

2.2.8 Énumération (recommandée)

Recommandé, thread-safe, chargement paresseux.

public enum Singleton {
    INSTANCE;

    public void sayHello() {
        System.out.println("Hello World");
    }
}
public class SingletonTest {
    public static void main(String[] args){
        Singleton instance = Singleton.INSTANCE;
        Singleton instance2 = Singleton.INSTANCE;
        System,out,println(instance == instance2);    //true
        System,out.println(instance.hashCode());
        System.out.println(instance2.hashCode());
    }
    public enum Singleton {
        INSTANCE;

        public void sayHello() {
            System.out.println("Hello World");
        }
    }
}

Avantages et inconvénients

  • 1) Cela implémente le modèle singleton à l'aide d'énumérations ajoutées dans JDK1.5. Non seulement peut éviter les problèmes de synchronisation multi-thread , mais également empêcher la désérialisation de recréer de nouveaux objets
  • 2) Cette approche est préconisée par l'auteur Java efficace Josh Bloch
  • 3) Conclusion : Il est recommandé d'utiliser

2.2.9 Analyse du mode singleton dans le code source du JDK

java.lang.Runtime dans JDK est le modèle singleton classique :

Style chinois affamé (variable statique) , sera certainement utilisé, alors n'ayez pas peur du gaspillage de mémoire

Guess you like

Origin blog.csdn.net/qq_40991313/article/details/130423855