Devdiaries
- Le motif d’usine
- Intention
- Solution du problème
- Structure du Motif d’usine
- Motif d’usine Abstrait
- Implémentation du Motif d’usine au printemps
- Motif d’usine utilisation populaire cas dans le cadre du Printemps
- Le modèle de constructeur
- Intention
- Solution du problème
- Structure du Modèle de Constructeur
- Implémentation du Modèle de constructeur au printemps
- Le motif Singleton
- Intention
- Solution du problème
- Structure du Motif Singleton
- Modèle Singleton exemple d’implémentation au printemps
- Motif Singleton vs Singletons de printemps
- Le modèle Prototype
- Intention
- Solution du problème
- Structure du Modèle Prototype
- Implémentation du modèle prototype au printemps
- Conclusion
Les modèles de conception créative traitent des mécanismes de création d’objets, en essayant de créer des objets d’une manière adaptée à la situation. Dans cet article, je vais décrire les modèles les plus populaires de cette catégorie et comment le printemps les utilise!
Le motif d’usine
Spring, en soi, est déjà un exemple d’implémentation du motif d’usine. Le motif est utilisé dans tout le cadre. L’un des principaux endroits où il est utilisé est la classe BeanFactory
.
Intention
- Le modèle d’usine permet la construction de classes similaires de différents types à l’aide d’une méthode d’usine
- L’appel de méthode crée l’objet pour vous
- Les objets créés sont des instances de classes qui partagent une interface ou une sous-classe
Solution au problème
- Grâce au modèle de conception d’usine, vous n’avez pas à vous soucier de la construction de la classe à plus d’un endroit.
- Il vous permet d’exploiter l’interface pour les opérations répétitives.
- Les bogues de copier-coller sont moins probables.
Structure du modèle d’usine
Tout d’abord, vous devez créer une interface commune que vous allez utiliser dans la fabrique d’objets. Ensuite, vous devez créer une classe qui crée des instances de votre inteface. Dans cette classe, vous devez implémenter une méthode qui serveur des classes concrètes que vous implémenterez ensuite à partir de l’interface elle-même. Donc, encore une fois, nous avons une classe qui a une méthode qui crée des instances de l’interface lorsqu’elle est en train de créer des instances dans la classe concrète.
Motif d’usine abstrait
Le motif d’usine abstrait est un motif très similaire au motif d’usine. Vous pouvez dire que c’est une usine d’usines. En un mot, il existe deux différences principales entre le modèle d’usine et l’usine abstraite:
- Modèle de conception d’usine abstrait crée Usine
- Modèle de conception d’usine crée des produits
public abstract class AbstractFactory { public abstract Product1Base CreateProduct1(); public abstract Product2Base CreateProduct2(); } class ConcreteFactory1 extends AbstractFactory{ @Override public Product1Base CreateProduct1() { return new ConcreteProduct1(); } @Override public Product2Base CreateProduct2() { return new ConcreteProduct2(); } } class ConcreteFactory2 extends AbstractFactory{ @Override public Product1Base CreateProduct1() { return new ConcreteAnotherProduct1(); } @Override public Product2Base CreateProduct2() { return new ConcreteAnotherProduct2(); } }
La classe AbstractFactory
est responsable de la création de plusieurs types différents (contrairement au modèle d’usine). Comme vous pouvez le voir dans l’exemple ci-dessus, chacune des usines peut être associée à différents objets au sein du même groupe (dans ce cas – produits).
Implémentation du modèle d’usine au printemps
Jetons un coup d’œil à l’interface ci-dessus:
public interface Animal { void setName(String name); String getName(); String getType(); void makeASound(); }
Animal
interface a plusieurs méthodes communes à tous les animaux (chaque animal a un type et un nom). Vous devez donc maintenant créer une nouvelle classe: AnimalFactory
@Component public class AnimalFactory { public Animal createAnimal(String type) { switch (type) { case "bird": return new Bird(); case "cat": return new Cat(); default: throw new UnsupportedOperationException("Unsupported animal type!"); } } }
J’ai ajouté l’annotation @Component
parce que je veux que le printemps gère cette usine. Il existe une méthode (méthode d’usine) qui renvoie un animal – createAnimal
. C’est une usine très simple qui ne supporte que deux types d’animaux (chat, oiseau). Si un autre type est fourni, une exception sera levée.
Créons un contrôleur à ressort – FactoryController
:
@RestController @RequestMapping("/") public class FactoryController { private AnimalFactory factory; @Autowired public FactoryController(AnimalFactory factory) { this.factory = factory; } @PostMapping("addAminal/{type}/{name}") public Animal addAnimal(@PathVariable String type, @PathVariable String name) { Animal animal = this.factory.createAnimal(type); animal.setName(name); animal.makeASound(); return animal; } }
J’ai ajouté une méthode @PostMapping
, que nous passerons par le type @PathVariable
et le nom de l’animal. En réponse, nous obtiendrons le nouvel objet animal créé par l’usine. Testons-le en utilisant un facteur : Journaux d’application:
Comme vous pouvez le voir, nous venons de créer un nouvel objet – un oiseau en utilisant notre usine.
Modèle d’usine cas d’utilisation populaires dans Spring Framework
Le framework Spring utilise le modèle de conception d’usine pour la création des objets en utilisant deux approches:
- Conteneur Spring BeanFactory (par exemple
org.springframework.beans.factory.BeanFactory
) – C’est le conteneur le plus simple du framework Spring qui fournit le support de base pour DI - Conteneur Spring ApplicationContext (e.g
) – t est un autre conteneur présent dans spring container qui ajoute des fonctionnalités supplémentaires spécifiques à l’entreprise telles que la publication d’événements d’application aux écouteurs d’événements attentifs ou le chargement de messages à partir d’un fichier de propriétés.
Comme vous pouvez le voir, whole Spring est déjà un exemple d’implémentation du modèle d’usine (le contexte d’application de toute application Spring n’est qu’une usine géante)
Le modèle de constructeur
Un autre modèle de création commun est le modèle de constructeur. L’utilisation populaire de Builder au printemps est ResultAction. Cette classe fait partie du MockMcv – utilisé pour tester des applications Web.
Intent
- Chaque méthode renvoie la référence d’objet à partir de laquelle elle est appelée.
- Il existe une méthode
build()
qui renvoie un objet entièrement configuré (basé sur tous les appels intermédiaires).
Solution du problème
- Améliore la lisibilité du code lorsque la création d’objets comporte de nombreux paramètres.
- Utile lorsque certains ou tous les paramètres sont facultatifs.
Structure du modèle de constructeur
Tout d’abord, vous devez définir une classe de base avec tous les constructeurs args. Ensuite, vous devez créer une classe de constructeur avec des attributs et des setters pour chaque argument de la classe de base. Chaque setter doit renvoyer le constructeur. Ensuite, vous devez créer un methid build()
qui construira et retournera l’objet de la classe de base.
Implémentation du modèle de constructeur au printemps
J’ai commencé mon implémentation avec une simple classe Java – Employee.java
:
public class Employee { private String firstName; private String lastName; private String employeeId; private String email; public Employee(String firstName, String lastName, String employeeId, String email) { this.firstName = firstName; this.lastName = lastName; this.employeeId = employeeId; this.email = email; } public Employee() { } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public String getEmployeeId() { return employeeId; } public String getEmail() { return email; } }
Il y a quelques attributs, contructor et getters générés automatiquement. Il est temps de mettre en œuvre le modèle de constructeur! Pour ce faire, créez la classe EmployeeBuilder
avec les mêmes champs que la classe Employee. Générez des setters – un pour chacun de nos champs. Si vous générez des setters parE, vous devez vous rappeler de changer le type renvoyé par setter (void) en EmployeeBuilder.
public class EmployeeBuilder { private String firstName; private String lastName; private String employeeId; private String email; // Each setter returns EmployeBuilder object. public EmployeeBuilder setFirstName(String firstName) { this.firstName = firstName; return this; } public EmployeeBuilder setLastName(String lastName) { this.lastName = lastName; return this; } public EmployeeBuilder setEmployeeId(String employeeId) { this.employeeId = employeeId; return this; } public EmployeeBuilder setEmail(String email) { this.email = email; return this; } public Employee buildEmployee() { return new Employee(firstName,lastName, employeeId, email); } }
À la fin, j’utilise la méthode public Employee buildEmployee()
qui crée l’employé. L’avantage de cette solution est que si l’un de nos champs est null, null sera rempli. Nous n’avons pas vraiment à penser à l’endroit où vont les nuls. Jetons un coup d’œil à l’action. J’ai créé BuilderController
Contrôleur de ressort qui a deux points de terminaison. Le premier crée un employé avec tous les champs, le second crée un employé sans e-mail:
@RestController @RequestMapping("/builder") public class BuilderController { @GetMapping("employee1") public Employee getEmployee1() { return new EmployeeBuilder() .setEmployeeId("1234") .setEmail("[email protected]") .setFirstName("John") .setLastName("smith") .buildEmployee(); } @GetMapping("employee2") public Employee getEmployee2() { return new EmployeeBuilder() .setEmployeeId("4321") .setFirstName("Jeff") .setLastName("Freeman") .buildEmployee(); } }
Comme vous vous y attendez probablement, la requête GET sur le premier point ed renvoie :
Le deuxième point de terminaison renvoie l’employé avec un null sous forme d’e-mail:
Le modèle Singleton
Singleton est un modèle utilisé par tous les développeurs Java qui utilisent Spring. Chaque bean est par défaut un singleton. Son but est de fournir la possibilité de créer un seul objet d’une classe donnée et de lui fournir un accès global.
Intent
- Il existe un seul constructeur privé.La classe
- stocke la référence à l’instance elle-même.
- Il existe une méthode getInstance() qui renvoie une référence d’instance de classe singleton ou construit un nouvel objet s’il n’est pas construit.
Dans le modèle Singleton, Java new Class
n’est jamais appelé sur la classe sauf le cas getInstance. Vous devez envelopper cette méthode avec une fonctionnalité de verrouillage pour assurer la sécurité multi-threads.
Solution au problème
Singleton peut être utilisé dans des cas:
- La création d’objets coûte cher.
- Classe qui stocke la configuration de l’application. De n’importe où dans le système, nous pouvons le modifier et nous voulons que les changements soient visibles de n’importe où. Dans le même temps, nous ne pouvons pas permettre la maintenance de différentes versions de configurations dans le système.
- Vous devez stocker l’état statique pour plusieurs parties de l’application.
- Vous devez contrôler qui a accès à un objet (contrôle de la concurrence).
Structure du modèle Singleton
Il existe de nombreuses façons d’implémenter un singleton, mais toutes peuvent être réduites à trois points principaux:
- Vous devez d’abord créer un constructeur privé dans votre classe Singleton
- Puis créer un handle d’instance qui est stocké dans la méthode class
- Create static
getInstance()
qui utilise un bloc synchronisé sur l’objet pour réduire le risque de sécurité du thread.
Exemple d’implémentation du modèle Singleton au printemps
Dans l’exemple suivant, nous allons implémenter notre propre Singleton. Ensuite, nous prouverons que les composants Spring sont des singletons par défaut. Commençons par créer quelques classes. Le premier que nous allons créer est la classe Singleton.java
qui sera un singleton traditionnel (décrit dans le point précédent):
public class Singleton { private static Singleton instance; private Singleton(){} public static Singleton getInstance() { if(null == instance){ synchronized (Singleton.class){ if(null==instance) { instance = new Singleton(); } } } return instance; } }
Maintenant, créez une classe Spring @Component
simple sans aucune logique:
@Component public class SpringSingleton { }
Ensuite, testons si nos singletons s’assurent qu’un seul objet est créé. J’ai utilisé le test JUnit (généré automatiquement lors de la création d’un projet Spring Boot dans Spring Initializer):
@RunWith(SpringRunner.class) @SpringBootTest public class SpringDesignPatternsApplicationTests { @Autowired SpringSingleton springSingleton1; @Autowired SpringSingleton springSingleton2; @Test public void singletonObjectsShouldBeEquals() { Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); // Checking if the Singleton objects are definitely one, the same object Assert.assertSame(singleton1, singleton2); // Checking if the spring components are definitely singletons Assert.assertSame(springSingleton1, springSingleton2); } }
assertSame()
la méthode vérifie si les arguments sont les mêmes objets. Résultat du test: réussi – tout était pareil. C’est ainsi que vous pouvez écrire des singletons traditionnels ou des singletons au printemps.
Motif Singleton vs Singletons printaniers
Il y a encore une chose à savoir. Comme je l’ai écrit – tous les haricots de printemps sont des singletons par défaut. Cependant, ce ne sont pas les mêmes singletons que les singletons traditionnels. Le modèle Singleton traditionnel suppose qu’il n’y a qu’une seule instance d’une classe donnée dans l’espace géré par Java classloader. Au printemps, il n’y a qu’une seule instance de Bean pour chaque instance de contexte donnée (_org.springframework.context.ApplicationContext
). Donc, si vous avez plus d’un contexte, tous gérés par le même chargeur de classe Java, vous aurez probablement plus d’une instance d’un bean.
Le modèle Prototype
Le prototype est un modèle dont le but est de copier des objets de l’objet parent. Dans le modèle prototype, un nouvel objet est créé en clonant un objet existant. En Java, la méthode clone()
est une implémentation de ce modèle de conception.
Intent
- L’instance est clonée à l’exécution pour donner de nouvelles instances ayant le même état
- En Java, C’est fait avec l’interface
Cloneable
/
Solution au problème
Le prototype peut être utilisé dans des cas:
- Vous devez créer de nombreuses instances d’objets identiques ou similaires, et le clonage est plus efficace que la création d’instances d’objets avec le nouveau mot clé Java.
- Utile avec des objets qui doivent être thread-safe et doivent stocker l’état (e.g paniers d’achat – où vous souhaitez avoir le même comportement, mais les articles individuels dans le panier sont différents)
Structure du modèle Prototype
- Créez une classe de base abstraite qui implémente Cloneable.
- Étend la classe abstraite dans les instances de prototype.
- Remplacez la méthode
clone()
dans ces instances de prototype – ajoutez le comportement spécifique à la classe.
Implémentation de PrototypePattern au printemps
Je n’implémenterai pas le prototype Java traditionnel. Cependant, je vais vous montrer comment créer un prototype de haricot au printemps. J’ai créé une classe stupide: SpringPrototype.java
public class SpringPrototype { }
Dans la classe d’application principale au printemps, j’ai défini un nouveau bean prototype en définissant @Scope
sur prototype:
@Bean @Scope("prototype") public SpringPrototype prototype(){ return new SpringPrototype(); }
Test de JUnit:
@Autowired SpringPrototype prototype1; @Autowired SpringPrototype prototype2; @Test public void prototypeObjectsShouldNotBeEquals() { Assert.assertNotSame(prototype1, prototype2); }
J’ai injecté deux instances de la classe SpringPrototype avec @Autowired
. Tout comme dans l’exemple Singleton – j’ai utilisé la méthode statique d’Assert pour vérifier que les instances créées ne sont pas les mêmes. Mon test est vert. C’est la preuve qu’il existe deux instances différentes du même objet.
Conclusion
J’espère que vous avez aimé le post. Nous devons connaître les modèles de création les plus importants utilisés au printemps. Dans le prochain article, nous allons en apprendre davantage sur les modèles structurels dans Spring Framework!
Write a Reply or Comment