Devdiaries
- Fabriksmönstret
- Intent
- problemlösning
- struktur av Fabriksmönstret
- Abstrakt Fabriksmönster
- fabriksmönster implementering under våren
- Fabriksmönster populär användning fall i Spring Framework
- Byggmönstret
- Intent
- problemlösning
- struktur för Byggmönstret
- Byggmönstrets implementering på våren
- Singleton mönstret
- Intent
- problemlösning
- struktur Singleton mönster
- Singleton mönster exemplifierande genomförande under våren
- Singleton mönster vs våren single
- prototypen mönster
- Intent
- problemlösning
- struktur av prototypen mönster
- Prototypmönster genomförande under våren
- slutsats
Creational design patterns handlar om objektskapande mekanismer, försöker skapa objekt på ett sätt som är lämpligt för situationen. I den här artikeln kommer jag att beskriva de mest populära mönstren i denna kategori och hur våren använder dem!
Fabriksmönstret
våren är i sig redan ett exempel på implementering av Fabriksmönstret. Mönstret används i hela ramverket. En av de främsta platserna som den används är klassen BeanFactory
.
Intent
- Fabriksmönster tillåter konstruktion av liknande klasser av olika typer med en fabriksmetod
- metodsamtal skapar objektet åt dig
- skapade objekt är instanser från klasser som delar ett gränssnitt eller underklass
problemlösning
- tack till fabriken designmönster du behöver inte oroa dig för klass konstruktion på mer än ett ställe.
- det låter dig utnyttja gränssnittet för repetitiva operationer.
- kopiera och klistra in buggar är mindre troliga.
struktur av Fabriksmönstret
för det första måste du skapa gemensamt gränssnitt som du ska använda i objektfabriken. Sedan måste du skapa en klass som skapar instanser av din inteface. I den klassen måste du implementera en metod som servrar konkreta klasser som du sedan kommer att implementera från själva gränssnittet. Så, igen, vi har en klass som har en metod som skapar instanser av gränssnittet när det är under täckningen att det faktiskt skapar instanser i betongklassen.
Abstrakt Fabriksmönster
Abstrakt Fabriksmönster är ett mönster som mycket liknar Fabriksmönstret. Du kan säga att det är fabrik av fabriker. I ett nötskal finns det två huvudskillnader mellan Fabriksmönstret och abstrakt fabrik:
- Abstrakt Fabriksdesignmönster skapar fabrik
- Fabriksdesignmönster skapar produkter
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(); } }
klassen AbstractFactory
ansvarar för att skapa flera olika typer (i motsats till Fabriksmönster). Som du kan se i exemplet ovan kan var och en av fabrikerna associeras med olika objekt inom samma grupp (i detta fall – produkter).
fabriksmönsterimplementering under våren
Låt oss ta en titt på ovanstående gränssnitt:
public interface Animal { void setName(String name); String getName(); String getType(); void makeASound(); }
Animal
gränssnittet har flera metoder som är gemensamma för alla djur (varje djur har en typ och ett namn). Så nu behöver du skapa en ny klass: 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!"); } } }
jag lade till @Component
annotation eftersom jag vill att våren ska hantera denna fabrik. Det finns en metod (fabriksmetod) som returnerar ett djur – createAnimal
. Det är en mycket enkel fabrik som stöder endast två typer av djur (Katt, Fågel). Om en annan typ tillhandahålls kommer ett undantag att kastas.
Låt oss skapa Vårkontroll – 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; } }
jag lade till en @PostMapping
– metod, som vi kommer att passera genom @PathVariable
– typen och namnet på djuret. Som svar kommer vi att få det nya djurobjektet skapat av fabriken. Låt oss testa det med en brevbärare: programloggar:
som du kan se har vi just skapat ett nytt objekt-en fågel med vår fabrik.
Fabriksmönster populära användningsfall i Spring Framework
Spring framework använder fabriksdesignmönstret för att skapa objekten genom att använda två tillvägagångssätt:
- Spring BeanFactory Container (t.ex.
org.springframework.beans.factory.BeanFactory
) – det är den enklaste behållaren i Spring framework som ger grundläggande stöd för Di - Spring ApplicationContext Container (e.g
)-t är en annan behållare som finns i spring container som lägger till extra företagsspecifik funktionalitet som att publicera applikationshändelser till de uppmärksamma händelselyssnarna eller ladda meddelanden från en egenskapsfil.
som du kan se är hela våren redan ett exempel på implementering av Fabriksmönstret (varje Vårapplikations applikationskontext är bara en jättefabrik)
Byggmönstret
ett annat vanligt kreationsmönster är Byggmönstret. Den populära användningen av byggare på våren är Resultatåtgärd. Denna klass är en del av MockMcv – används för att testa webbapplikationer.
Intent
- varje metod returnerar objektreferensen den anropas från.
- det finns
build()
metod som returnerar ett helt konstruerat objekt (baserat på alla mellanliggande samtal).
problemlösning
- förbättrar läsbarheten för koden när objektskapande har många parametrar.
- användbart när vissa eller alla paramaters är valfria.
struktur för Byggmönstret
för det första måste du definiera en basklass med alla args-konstruktörer. Sedan måste du skapa en Byggarklass med attribut och setters för varje argument i basklassen. Varje setter ska returnera byggaren. Då måste du skapa en build()
methid som kommer att konstruera och returnera objekt av basklass.
Builder mönsterimplementering på våren
jag började min implementering med en enkel Java-klass – 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; } }
det finns ett par attribut, contructor och auto-genererade getters. Det är dags att implementera builder pattern! För att göra detta, skapa klassen EmployeeBuilder
med samma fält som Anställdsklassen. Generera setters-en för vart och ett av våra fält. Om du skapar setters av IDE, måste du komma ihåg att ändra den typ som returneras av setter (void) till 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); } }
i slutet använder jag public Employee buildEmployee()
– metoden som skapar medarbetaren. Fördelen med denna lösning är att om något av våra fält är null kommer null att fyllas i. Vi behöver inte riktigt tänka på var nollorna går. Låt oss ta en titt på åtgärder. Jag skapade BuilderController
Spring controller som har två slutpunkter. Den första skapar en anställd med alla fält, den andra skapar en anställd utan e-post:
@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(); } }
som du förmodligen förväntar dig returnerar GET-förfrågan på den första edpoint:
den andra slutpunkten returnerar medarbetaren med ett null som ett e-postmeddelande:
Singleton-mönstret
Singleton är ett mönster som används av alla Java-utvecklare som använder Spring. Varje böna är som standard en singleton. Dess syfte är att ge möjlighet att skapa endast ett objekt i en viss klass och ge global tillgång till den.
Intent
- det finns en enda privat konstruktör.
- klass lagrar hänvisning till förekomsten av sig själv.
- det finns getInstance () metod som returnerar en referens av singleton klass instans eller konstruerar nytt objekt om det inte konstrueras.
i Singleton-mönster anropas Java new Class
aldrig klassen utom getInstance-fallet. Du bör lägga in den här metoden med viss låsningsfunktionalitet för att säkerställa flertråds säkerhet.
problemlösning
Singleton kan användas i fall:
- objektskapande är dyrt.
- klassen som lagrar programkonfigurationen. Från var som helst i systemet kan vi ändra det och vi vill att ändringarna ska vara synliga var som helst. Samtidigt kan vi inte tillåta att olika versioner av konfigurationer upprätthålls i systemet.
- du måste lagra statiskt tillstånd för flera delar av programmet.
- du måste kontrollera vem som har tillgång till ett objekt (samtidighetskontroll).
struktur för Singleton-mönstret
det finns många sätt att implementera en singleton, men alla kan reduceras till tre huvudpunkter:
- först måste du skapa en privat konstruktör i din Singleton-klass
- skapa sedan ett instanshandtag som lagras i klassen
- skapa statisk
getInstance()
metod som använder ett synkroniserat block på objektet för att minska trådsäkerhetsrisken.
Singleton mönster exemplifierande implementering under våren
i följande exempel kommer vi att implementera vår egen Singleton. Då kommer vi att bevisa att Fjäderkomponenterna är singletons som standard. Låt oss börja med att skapa ett par klasser. Den första vi ska skapa är Singleton.java
klass som kommer att vara en traditionell singleton (beskrivs i föregående punkt):
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; } }
skapa nu Enkel Vår @Component
klass utan logik:
@Component public class SpringSingleton { }
Låt oss sedan testa om våra singletons säkerställer att endast ett objekt skapas. Jag använde JUnit-testet (genererades automatiskt när jag skapade ett Spring Boot-projekt i 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()
metoden kontrollerar om argument är samma objekt. Testresultat: godkänd-allt var detsamma. Så kan du skriva traditionella singletons eller singletons på våren.
Singleton mönster vs Spring Singletons
det finns en sak du bör veta. Som jag skrev-alla Vårbönor är singletons som standard. Dessa är dock inte samma singletons som de traditionella singletons. Det traditionella Singleton-mönstret förutsätter att det bara finns en instans av en viss klass på det utrymme som hanteras av Java classloader. På våren finns det bara en instans av bönor för varje givet sammanhang (_org.springframework.context.ApplicationContext
) instans. Så, om du har mer än ett sammanhang, Alla hanteras av samma Java classloader, du kommer förmodligen att ha mer än en instans av en böna.
Prototypmönstret
prototypen är ett mönster vars syfte är att kopiera objekt från det överordnade objektet. I prototypmönstret skapas ett nytt objekt genom att klona ett befintligt objekt. I Java är metoden clone()
en implementering av detta designmönster.
Intent
- instans klonas vid körning för att ge nya instanser som har samma tillstånd
- i Java görs det med gränssnittet
Cloneable
/
problemlösning
prototypen kan användas i fall:
- du måste skapa många instanser av samma eller liknande objekt, och kloning är effektivare än att skapa instanser av objekt med det nya Java-sökordet.
- användbar med objekt som måste vara tråd säker och måste lagra tillstånd (e.g kundvagnar – där du vill ha samma beteende men de enskilda artiklarna i vagnen är olika)
struktur av Prototypmönstret
- skapa en abstrakt basklass som implementerar Cloneable.
- utöka abstrakt klass i prototypinstanser.
- åsidosätta metoden
clone()
i dessa prototypinstanser – Lägg till klassspecifikt beteende.
Prototypmönster implementering under våren
jag kommer inte att implementera den traditionella Java-prototypen. Men jag kommer att visa dig hur man skapar en prototypböna på våren. Jag skapade en dum klass: SpringPrototype.java
public class SpringPrototype { }
i huvudapplikationsklassen på våren definierade jag en ny prototypböna genom att ställa in @Scope
till prototyp:
@Bean @Scope("prototype") public SpringPrototype prototype(){ return new SpringPrototype(); }
JUnit test:
@Autowired SpringPrototype prototype1; @Autowired SpringPrototype prototype2; @Test public void prototypeObjectsShouldNotBeEquals() { Assert.assertNotSame(prototype1, prototype2); }
jag injicerade två instanser av Springprototyp klassen med @Autowired
. Precis som i Singleton – exemplet-använde jag Den statiska metoden från Assert för att kontrollera att de skapade instanserna inte är desamma. Mitt test är grönt. Det är ett bevis på att det finns två olika instanser av samma objekt.
slutsats
jag hoppas att du gillade inlägget. Vi måste känna till de viktigaste kreationsmönstren som används på våren. I nästa inlägg kommer vi att lära oss om strukturella mönster i Spring Framework!
Write a Reply or Comment