Introduktion til Creational Design Patterns

1. Introduktion

I softwareteknik beskriver et designmønster en etableret løsning på de mest almindelige problemer i softwaredesign. Det repræsenterer de bedste fremgangsmåder, der er udviklet over en lang periode gennem forsøg og fejl fra erfarne softwareudviklere.

Designmønstre blev populær efter bogen Designmønstre: Elementer af genanvendelig objektorienteret software blev udgivet i 1994 af Erich Gamma, John Vlissides, Ralph Johnson og Richard Helm (også kendt som Gang of Four eller GoF).

I denne artikel vil vi undersøge skabelsesmønstre og deres typer. Vi ser også på nogle kodeeksempler og diskuterer situationerne, når disse mønstre passer til vores design.

2. Kreative designmønstre

Creational Design Mønstre beskæftiger sig med den måde, hvorpå objekter oprettes. De reducerer kompleksiteten og ustabiliteten ved at skabe objekter på en kontrolleret måde.

Det ny operatøren betragtes ofte som skadelig, da den spreder objekter overalt i applikationen. Over tid kan det blive udfordrende at ændre en implementering, fordi klasser bliver tæt koblet.

Creational Design Patterns løser dette problem ved at afkoble klienten helt fra den faktiske initialiseringsproces.

I denne artikel vil vi diskutere fire typer kreativt designmønster:

  1. Singleton - Sikrer, at der højst kun findes en forekomst af et objekt i hele applikationen
  2. Fabriksmetode - Opretter objekter fra flere relaterede klasser uden at specificere det nøjagtige objekt, der skal oprettes
  3. Abstrakt fabrik - Opretter familier af relaterede afhængige objekter
  4. ByggerKonstruerer komplekse objekter ved hjælp af trin-for-trin tilgang

Lad os nu diskutere hvert af disse mønstre detaljeret.

3. Singleton designmønster

Singleton Design Pattern har til formål at kontrollere initialiseringen af ​​objekter fra en bestemt klasse ved sikre, at der kun findes en forekomst af objektet i hele Java Virtual Machine.

En Singleton-klasse giver også et unikt globalt adgangspunkt til objektet, så hvert efterfølgende opkald til adgangspunktet kun returnerer det bestemte objekt.

3.1. Eksempel på Singleton-mønster

Selvom Singleton-mønsteret blev introduceret af GoF, er den oprindelige implementering kendt for at være problematisk i multitrådede scenarier.

Så her skal vi følge en mere optimal tilgang, der gør brug af en statisk indre klasse:

offentlig klasse Singleton {privat Singleton () {} privat statisk klasse SingletonHolder {offentlig statisk endelig Singleton-forekomst = ny Singleton (); } offentlig statisk Singleton getInstance () {return SingletonHolder.instance; }}

Her har vi oprettet en statisk indre klasse, der holder instansen af Singleton klasse. Det opretter kun forekomsten, når nogen ringer til getInstance () metode og ikke når den ydre klasse er indlæst.

Dette er en meget anvendt tilgang til en Singleton-klasse, da den ikke kræver synkronisering, er trådsikker, håndhæver doven initialisering og har relativt mindre kedelplade.

Bemærk også, at konstruktøren har privat adgangsmodifikator. Dette er et krav for at oprette en Singleton, da en offentlig konstruktør ville betyde, at enhver kunne få adgang til det og begynde at oprette nye forekomster.

Husk, dette er ikke den originale GoF-implementering. For den originale version, se venligst denne linkede Baeldung-artikel om Singletons i Java.

3.2. Hvornår skal man bruge Singleton Design Pattern?

  • For ressourcer, der er dyre at oprette (som objekt til databaseforbindelse)
  • Det er god praksis at holde alle loggere som Singletons, hvilket øger ydeevnen
  • Klasser, der giver adgang til konfigurationsindstillinger for applikationen
  • Klasser, der indeholder ressourcer, der er adgang til i delt tilstand

4. Fabriksmetode designmønster

Factory Design Pattern eller Factory Method Design Pattern er et af de mest anvendte designmønstre i Java.

Ifølge GoF er dette mønster “Definerer en grænseflade til oprettelse af et objekt, men lad underklasser bestemme, hvilken klasse der skal instantieres. Fabriksmetoden lader en klasse udsætte instantiering til underklasser ”.

Dette mønster delegerer ansvaret for at initialisere en klasse fra klienten til en bestemt fabriksklasse ved at oprette en type virtuel konstruktør.

For at opnå dette stoler vi på en fabrik, der forsyner os med objekterne og skjuler de faktiske implementeringsoplysninger. Der er adgang til de oprettede objekter ved hjælp af en fælles grænseflade.

4.1. Fabriksmetode Designmønstereksempel

I dette eksempel opretter vi en Polygon interface, som vil blive implementeret af flere konkrete klasser. EN PolygonFabrik vil blive brugt til at hente objekter fra denne familie:

Lad os først oprette Polygon grænseflade:

offentlig grænseflade Polygon {String getType (); }

Dernæst opretter vi et par implementeringer som Firkant, Trekant, osv., der implementerer denne grænseflade og returnerer et objekt af Polygon type.

Nu kan vi oprette en fabrik, der tager antallet af sider som et argument og returnerer den passende implementering af denne grænseflade:

public class PolygonFactory {public Polygon getPolygon (int numberOfSides) {if (numberOfSides == 3) {return new Triangle (); } hvis (numberOfSides == 4) {returner ny firkant (); } hvis (numberOfSides == 5) {returner ny Pentagon (); } hvis (numberOfSides == 7) {returner nyt Heptagon (); } ellers hvis (numberOfSides == 8) {returner ny Octagon (); } returnere null; }}

Læg mærke til, hvordan klienten kan stole på, at denne fabrik giver os en passende Polygonuden at skulle initialisere objektet direkte.

4.2. Hvornår skal man bruge fabriksmetode designmønster

  • Når implementeringen af ​​en grænseflade eller en abstrakt klasse forventes at ændre sig ofte
  • Når den nuværende implementering ikke komfortabelt kan rumme nye ændringer
  • Når initialiseringsprocessen er relativt enkel, og konstruktøren kun kræver en håndfuld parametre

5. Abstrakt fabriksmønster

I det forrige afsnit så vi, hvordan designmønsteret fra Factory Method kunne bruges til at skabe objekter relateret til en enkelt familie.

Derimod bruges det abstrakte fabriksdesignmønster til at skabe familier med relaterede eller afhængige objekter. Det kaldes også undertiden en fabrik med fabrikker.

For en detaljeret forklaring, se vores abstrakte fabriksvejledning.

6. Builder design mønster

Builder Design Pattern er et andet skabelsesmønster designet til at håndtere konstruktionen af ​​forholdsvis komplekse objekter.

Når kompleksiteten ved at skabe objekt øges, kan Builder-mønsteret adskille instantieringsprocessen ved at bruge et andet objekt (en builder) til at konstruere objektet.

Denne builder kan derefter bruges til at oprette mange andre lignende repræsentationer ved hjælp af en simpel trin-for-trin tilgang.

6.1. Byggemønstereksempel

Det originale Builder Design-mønster introduceret af GoF fokuserer på abstraktion og er meget godt, når man beskæftiger sig med komplekse objekter, men designet er dog lidt kompliceret.

Joshua Bloch introducerede i sin bog Effektiv Java en forbedret version af bygmønsteret, som er rent, meget læsbart (fordi det gør brug af flydende design) og let at bruge fra kundens perspektiv. I dette eksempel vil vi diskutere den version.

Dette eksempel har kun en klasse, Bankkonto der indeholder en bygherre som en statisk indre klasse:

offentlig klasse BankAccount {privat strengnavn; privat streng kontoNummer; privat streng e-mail; privat boolsk nyhedsbrev; // constructors / getters public static class BankAccountBuilder {// builder code}} 

Bemærk, at alle adgangsmodifikatorer på felterne er deklareret privat da vi ikke vil have ydre objekter direkte adgang til dem.

Konstruktøren er også privat så kun den Builder, der er tildelt denne klasse, kan få adgang til den. Alle egenskaber, der er indstillet i konstruktøren, udvindes fra bygherreobjektet, som vi leverer som et argument.

Vi har defineret BankAccountBuilder i en statisk indre klasse:

offentlig statisk klasse BankAccountBuilder {privat strengnavn; privat streng kontoNummer; privat streng e-mail; privat boolsk nyhedsbrev; public BankAccountBuilder (String name, String accountNumber) {this.name = name; this.accountNumber = accountNumber; } offentlig BankAccountBuilder withEmail (streng e-mail) {this.email = email; returner dette; } offentlig BankAccountBuilder wantNewsletter (boolsk nyhedsbrev) {this.newsletter = newsletter; returner dette; } public BankAccount build () {return new BankAccount (this); }} 

Bemærk, at vi har erklæret det samme sæt felter, som den ydre klasse indeholder. Alle obligatoriske felter kræves som argumenter for den indre klasses konstruktør, mens de resterende valgfrie felter kan specificeres ved hjælp af settermetoderne.

Denne implementering understøtter også den flydende designtilgang ved at lade settermetoderne returnere bygherreobjektet.

Endelig kalder buildmetoden den private konstruktør i den ydre klasse og overfører sig selv som argumentet. De returnerede Bankkonto vil blive instanseret med de parametre, der er indstillet af BankAccountBuilder.

Lad os se et hurtigt eksempel på bygmønsteret i aktion:

BankAccount newAccount = new BankAccount .BankAccountBuilder ("Jon", "22738022275") .withEmail ("[email protected]") .wantNewsletter (true) .build ();

6.2. Hvornår skal man bruge Builder-mønster

  1. Når processen involveret i oprettelse af et objekt er ekstremt kompleks med mange obligatoriske og valgfri parametre
  2. Når en stigning i antallet af konstruktorparametre fører til en stor liste over konstruktører
  3. Når klienten forventer forskellige repræsentationer for det objekt, der er konstrueret

7. Konklusion

I denne artikel lærte vi om skabelsesmønstre i Java. Vi diskuterede også deres fire forskellige typer, dvs. Singleton, Factory Method, Abstract Factory og Builder Pattern, deres fordele, eksempler og hvornår skal vi bruge dem.

Som altid er de komplette kodestykker tilgængelige på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found