Devdiaries
- Il modello Factory
- Intento
- la Soluzione del Problema
- Struttura del Modello Factory
- Abstract Factory Pattern
- Fabbrica Modello di attuazione in Primavera
- Factory Pattern di uso popolare dei casi nella Primavera del Quadro
- Il Generatore di pattern
- Intento
- la Soluzione del Problema
- Struttura del Generatore di Pattern
- Generatore di Pattern di attuazione in Primavera
- Il Singleton pattern
- Intento
- la Soluzione del Problema
- Struttura del Singleton Pattern
- Singleton Pattern esemplare di attuazione in Primavera
- Singleton Pattern vs Primavera Singleton
- Il Prototipo di modello
- Intento
- la Soluzione del Problema
- Struttura del Prototipo Modello
- PrototypePattern attuazione in Primavera
- Conclusione
pattern creazionali modelli di progettazione che fare con la creazione di un oggetto meccanismi, cercando di creare oggetti in un modo adatto alla situazione. In questo articolo, descriverò i modelli più popolari in questa categoria e come la primavera li usa!
Il modello di fabbrica
Spring, di per sé, è già un’implementazione di esempio del modello di fabbrica. Il modello viene utilizzato in tutto l’intero framework. Uno dei luoghi principali in cui viene utilizzato è la classe BeanFactory
.
Intento
- modello Factory permette la costruzione di classi simili di diversi tipi, utilizzando un metodo factory
- chiamata al Metodo crea l’oggetto per voi
- Creato gli oggetti sono istanze di classi che condividono un’interfaccia o sottoclasse
la Soluzione del Problema
- Grazie alla Fabbrica di Design Pattern non è necessario preoccuparsi di classe costruzione in più di un posto.
- Consente di sfruttare l’interfaccia per operazioni ripetitive.
- I bug di copia-incolla sono meno probabili.
Struttura del modello di fabbrica
In primo luogo, è necessario creare un’interfaccia comune che si intende utilizzare in objects factory. Quindi, è necessario creare una classe che crea istanze del tuo inteface. In quella classe, devi implementare un metodo che server classi concrete che implementerai dall’interfaccia stessa. Quindi, di nuovo, abbiamo una classe che ha un metodo che crea istanze dell’interfaccia quando sotto la copertura che sta effettivamente creando istanze nella classe concrete.
Abstract Factory Pattern
Abstract Factory Pattern è un modello molto simile al modello di fabbrica. Si può dire che è Fabbrica di fabbriche. In poche parole, ci sono due differenze principali tra il modello di fabbrica e la fabbrica astratta:
- Abstract Factory design pattern crea Fabbrica
- Factory design pattern crea prodotti
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
è responsabile della creazione di diversi tipi (in contrasto con il modello di fabbrica). Come puoi vedere nell’esempio precedente, ciascuna delle fabbriche può essere associata a oggetti diversi all’interno dello stesso gruppo (in questo caso – prodotti).
Implementazione del modello di fabbrica in primavera
Diamo un’occhiata all’interfaccia sopra:
public interface Animal { void setName(String name); String getName(); String getType(); void makeASound(); }
Animal
interfaccia ha diversi metodi che sono comuni a tutti gli animali (ogni animale ha un tipo e un nome). Quindi, ora è necessario creare una nuova 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!"); } } }
Ho aggiunto @Component
annotazione perché voglio che la molla gestisca questa fabbrica. Esiste un metodo (metodo di fabbrica) che restituisce un animale – createAnimal
. È una fabbrica molto semplice che supporta solo due tipi di animali (gatto, uccello). Se viene fornito un altro tipo, verrà generata un’eccezione.
Creiamo il regolatore della molla – 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; } }
Ho aggiunto un metodo @PostMapping
, che passeremo attraverso il tipo e il nome dell’animale @PathVariable
. In risposta, otterremo il nuovo oggetto animale creato dalla fabbrica. Testiamolo usando un postino: Log delle applicazioni:
Come puoi vedere, abbiamo appena creato un nuovo oggetto: un uccello usando la nostra fabbrica.
Factory Pattern di uso popolare dei casi in Spring Framework
Il framework Spring utilizza la fabbrica modello di progettazione per la creazione di oggetti utilizzando due approcci:
- Primavera BeanFactory Contenitore (e.g
org.springframework.beans.factory.BeanFactory
) – è il più semplice contenitore di Spring framework che fornisce il supporto di base per DI - Primavera ApplicationContext Contenitore (e.g
) – t è un altro contenitore presente nel contenitore spring che aggiunge funzionalità extra specifiche dell’azienda come la pubblicazione di eventi dell’applicazione agli ascoltatori di eventi attenti o il caricamento di messaggi da un file di proprietà.
Come puoi vedere, whole Spring è già un’implementazione di esempio del pattern Factory (il contesto applicativo di qualsiasi applicazione Spring è solo una fabbrica gigante)
Il pattern Builder
Un altro pattern creazionale comune è il pattern Builder. L’uso popolare del costruttore in primavera è il risultatoazione. Questa classe fa parte del MockMcv – utilizzato per testare le applicazioni web.
Intent
- Ogni metodo restituisce il riferimento all’oggetto da cui viene chiamato.
- Esiste un metodo
build()
che restituisce un oggetto completamente contstructed (basato su tutte le chiamate intermedie).
Soluzione del problema
- Migliora la leggibilità del codice quando la creazione di oggetti ha molti parametri.
- Utile quando alcuni o tutti i parametri sono opzionali.
Struttura del pattern Builder
In primo luogo, è necessario definire una classe base con tutto il costruttore args. Quindi, devi creare una classe Builder con attributi e setter per ogni argomento della classe base. Ogni setter dovrebbe restituire il costruttore. Quindi, è necessario creare un methid build()
che costruirà e restituirà l’oggetto della classe base.
Implementazione del modello Builder in Spring
Ho iniziato la mia implementazione con una semplice 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; } }
Ci sono un paio di attributi, contructor e getter generati automaticamente. È tempo di implementare il modello builder! Per fare ciò, creare la classe EmployeeBuilder
con gli stessi campi della classe Employee. Genera setter-uno per ciascuno dei nostri campi. Se si generano setter per IDE, è necessario ricordare di modificare il tipo restituito da setter (void) in 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); } }
Alla fine uso il metodo public Employee buildEmployee()
che crea il dipendente. Il vantaggio di questa soluzione è che se uno qualsiasi dei nostri campi è null, null verrà popolato. Non dobbiamo davvero pensare a dove vanno i null. Diamo un’occhiata all’azione. Ho creato BuilderController
Spring controller che ha due endpoint. La prima crea un dipendente con tutti i campi, il secondo crea un dipendente senza un’email:
@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(); } }
Come probabilmente prevedibile, la richiesta GET al primo edpoint restituisce:
Il secondo endpoint restituisce il dipendente con un null email:
Il Singleton pattern
Singleton è un modello utilizzato da ogni sviluppatore Java che utilizza la Primavera. Ogni bean è di default un singleton. Il suo scopo è quello di fornire la possibilità di creare solo un oggetto di una determinata classe e fornire accesso globale ad esso.
Intent
- Esiste un solo costruttore privato.
- Class memorizza il riferimento all’istanza di se stesso.
- Esiste un metodo getInstance() che restituisce un riferimento di istanza di classe singleton o costruisce un nuovo oggetto se non costruito.
Nel modello Singleton, Java new Class
non viene mai chiamato sulla classe tranne il caso getInstance. Dovresti avvolgere questo metodo con alcune funzionalità di blocco per garantire la sicurezza multi-thread.
Soluzione del problema
Singleton può essere utilizzato nei casi:
- La creazione di oggetti è costosa.
- La classe che memorizza la configurazione dell’applicazione. Da qualsiasi punto del sistema, possiamo modificarlo e vogliamo che le modifiche siano visibili da qualsiasi luogo. Allo stesso tempo, non possiamo consentire che diverse versioni di configurazioni vengano mantenute nel sistema.
- È necessario memorizzare lo stato statico per più parti dell’applicazione.
- È necessario controllare chi ha accesso a un oggetto (controllo della concorrenza).
Struttura del Singleton Pattern
Ci sono molti modi per implementare un singleton, ma tutto può essere ridotto a tre punti principali:
- Innanzitutto, è necessario creare un costruttore privato nella vostra classe Singleton
- Quindi, creare un handle di istanza che è memorizzato nella classe
- Creare statico
getInstance()
metodo che utilizza un blocco sincronizzato sull’oggetto per ridurre il thread rischio per la sicurezza.
Modello Singleton implementazione esemplare in primavera
Nel seguente esempio, implementeremo il nostro Singleton. Quindi dimostreremo che i componenti della molla sono singleton per impostazione predefinita. Iniziamo con la creazione di un paio di classi. La prima che creeremo è la classe Singleton.java
che sarà un singleton tradizionale (descritto nel punto precedente):
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; } }
Ora, crea una semplice classe Spring @Component
senza alcuna logica:
@Component public class SpringSingleton { }
Quindi, verifichiamo se i nostri singleton assicurano che venga creato un solo oggetto. Ho usato il test JUnit (generato automaticamente durante la creazione di un progetto di avvio a molla in 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()
il metodo controlla se gli argomenti sono gli stessi oggetti. Risultato del test: superato-tutto era lo stesso. È così che puoi scrivere singleton o singleton tradizionali in primavera.
Singleton Pattern vs Spring Singleton
C’è un’altra cosa che dovresti sapere. Come ho scritto – tutti i fagioli primaverili sono singleton per impostazione predefinita. Tuttavia, questi non sono gli stessi single dei single tradizionali. Il modello Singleton tradizionale presuppone che ci sia solo un’istanza di una determinata classe nello spazio gestito da Java classloader. In primavera, c’è solo un’istanza di Bean per ogni istanza di contesto specificato (_org.springframework.context.ApplicationContext
). Quindi, se hai più di un contesto, tutto gestito dallo stesso classloader Java, probabilmente avrai più di un’istanza di un bean.
Il modello prototipo
Il prototipo è un modello il cui scopo è copiare oggetti dall’oggetto genitore. Nel modello prototipo, viene creato un nuovo oggetto clonando un oggetto esistente. In Java, il metodo clone()
è un’implementazione di questo modello di progettazione.
Intento
- Istanza viene clonato in fase di esecuzione per dare nuove istanze che hanno lo stesso stato
- In Java È fatto con il
Cloneable
interfaccia/
la Soluzione del Problema
Il prototipo può essere utilizzato nei casi in:
- È necessario creare un sacco di istanze dello stesso o di oggetti simili, e la clonazione è più efficiente della creazione di istanze di oggetti con la nuova versione di Java parola chiave.
- Utile con oggetti che devono essere thread safe e devono memorizzare lo stato (e.g carrelli-dove si desidera avere lo stesso comportamento ma i singoli articoli nel carrello sono diversi)
Struttura del modello prototipo
- Crea una classe base astratta che implementa Cloneable.
- Estendere la classe astratta nelle istanze prototype.
- Ignorare il metodo
clone()
in tali istanze prototipo – aggiungere il comportamento specifico della classe.
Implementazione di PrototypePattern in Spring
Non implementerò il tradizionale prototipo Java. Tuttavia, vi mostrerò come creare un bean prototipo in primavera. Ho creato una classe muto: SpringPrototype.java
public class SpringPrototype { }
Nella classe principale dell’applicazione, in Primavera, ho definito definito un nuovo prototipo di fagioli impostando @Scope
per prototipo:
@Bean @Scope("prototype") public SpringPrototype prototype(){ return new SpringPrototype(); }
test JUnit:
@Autowired SpringPrototype prototype1; @Autowired SpringPrototype prototype2; @Test public void prototypeObjectsShouldNotBeEquals() { Assert.assertNotSame(prototype1, prototype2); }
ho iniettato due istanze di SpringPrototype classe con @Autowired
. Proprio come nell’esempio Singleton – Ho usato il metodo statico da Assert per verificare che le istanze create non siano le stesse. Il mio test è verde. È la prova che ci sono due istanze diverse dello stesso oggetto.
Conclusione
Spero che ti sia piaciuto il post. Abbiamo avuto modo di conoscere i modelli creativi più importanti utilizzati in primavera. Nel prossimo post, impareremo a conoscere i modelli strutturali nel quadro di primavera!
Scrivi una risposta o commento.