Formidlermønsteret i Java

1. Oversigt

I denne artikel vil vi se på Mediator-mønsteret, et af GoF's adfærdsmønstre. Vi beskriver dets formål og forklarer, hvornår vi skal bruge det.

Som sædvanligt giver vi også et simpelt kodeeksempel.

2. Mæglermønster

I objektorienteret programmering skal vi altid prøve at design systemet på en sådan måde, at komponenterne er løst koblet og genanvendelige. Denne tilgang gør vores kode lettere at vedligeholde og teste.

I det virkelige liv har vi dog ofte brug for et komplekst sæt afhængige objekter. Dette er når mediatormønsteret kan være nyttigt.

Formålet med mediatormønsteret er at reducere kompleksiteten og afhængighederne mellem tæt koblede objekter, der kommunikerer direkte med hinanden. Dette opnås ved at skabe et mediatorobjekt, der tager sig af interaktionen mellem afhængige objekter. Derfor går al kommunikation gennem mægleren.

Dette fremmer løs kobling, da et sæt komponenter, der arbejder sammen ikke længere behøver at interagere direkte. I stedet henviser de kun til det enkelte mediatorobjekt. På denne måde er det også lettere at genbruge disse objekter i andre dele af systemet.

3. UML-diagram for mediatormønster

Lad os nu se på mønsteret visuelt:

I ovenstående UML-diagram kan vi identificere følgende deltagere:

  • Mægler definerer grænsefladen Kollega genstande bruger til at kommunikere
  • Kollega definerer den abstrakte klasse, der indeholder en enkelt henvisning til Mægler
  • ConcreteMediator indkapsler interaktionslogikken mellem Kollega genstande
  • BetonKollega1 og BetonColleague2 kun kommunikere gennem Mægler

Som vi kan se, Kollega objekter henviser ikke direkte til hinanden. I stedet udføres al kommunikation af Mægler.

Følgelig, BetonKollega1 og BetonColleague2 kan lettere genbruges.

Også, hvis vi har brug for at ændre vejen Kollega genstande arbejder sammen, skal vi kun ændre ConcreteMediator logik. Eller vi kan skabe en ny implementering af Mægler.

4. Java-implementering

Nu hvor vi har en klar idé om teorien, skal vi se på et eksempel for bedre at forstå konceptet i praksis.

4.1. Eksempel på scenarie

Forestil dig, at vi bygger et simpelt kølesystem, der består af en blæser, en strømforsyning og en knap. Ved at trykke på knappen tændes eller slukkes blæseren. Før vi tænder blæseren, skal vi tænde for strømmen. På samme måde skal vi slukke for strømmen lige efter at blæseren er slukket.

Lad os nu se på implementeringen af ​​eksemplet:

public class Button {privat ventilator; // constructor, getters and setters public void press () {if (fan.isOn ()) {fan.turnOff (); } andet {fan.turnOn (); }}}
offentlig klasse fan {knap til privat knap; private PowerSupplier powerSupplier; privat boolsk isOn = falsk; // constructor, getters and setters public void turnOn () {powerSupplier.turnOn (); isOn = sand; } offentlig ugyldig turnOff () {isOn = false; powerSupplier.turnOff (); }}
offentlig klasse PowerSupplier {public void turnOn () {// implementering} public void turnOff () {// implementering}}

Lad os derefter teste funktionaliteten:

@Test offentlig ugyldighed givenTurnedOffFan_whenPressingButtonTwice_fanShouldTurnOnAndOff () {assertFalse (fan.isOn ()); knap. tryk på (); assertTrue (fan.isOn ()); knap. tryk på (); assertFalse (fan.isOn ()); }

Alt ser ud til at fungere fint. Men bemærk hvordan Knap, blæser, og Strømforsyning klasser er tæt koblet. Det Knap fungerer direkte på Ventilator og Ventilator interagerer med begge dele Knap og Strømforsyning.

Det ville være svært at genbruge Knap klasse i andre moduler. Også, hvis vi har brug for at tilføje en anden strømforsyning til vores system, bliver vi nødt til at ændre Ventilator klassens logik.

4.2. Tilføjelse af mediatormønsteret

Lad os nu implementere Mediator-mønsteret for at reducere afhængighederne mellem vores klasser og gøre koden mere genanvendelig.

Lad os først introducere Mægler klasse:

offentlig klasse mægler {knap til privat knap; privat ventilator; private PowerSupplier powerSupplier; // constructor, getters and setters public void press () {if (fan.isOn ()) {fan.turnOff (); } andet {fan.turnOn (); }} offentlig ugyldig start () {powerSupplier.turnOn (); } offentligt ugyldigt stop () {powerSupplier.turnOff (); }}

Lad os derefter ændre de resterende klasser:

offentlig klasse knap {privat mægler mægler; // constructor, getters and setters public void press () {mediator.press (); }}
offentlig klasse Fan {privat mægler mægler; privat boolsk isOn = falsk; // constructor, getters and setters public void turnOn () {mediator.start (); isOn = sand; } offentlig ugyldig turnOff () {isOn = false; mediator.stop (); }}

Lad os igen teste funktionaliteten:

@Test offentlig ugyldighed givenTurnedOffFan_whenPressingButtonTwice_fanShouldTurnOnAndOff () {assertFalse (fan.isOn ()); knap. tryk på (); assertTrue (fan.isOn ()); knap. tryk på (); assertFalse (fan.isOn ()); }

Vores kølesystem fungerer som forventet.

Nu hvor vi har implementeret Mediator-mønsteret, er der ingen af Knap, Ventilator, eller Strømforsyning klasser kommunikerer direkte. De har kun en enkelt henvisning til Mægler.

Hvis vi har brug for at tilføje en anden strømforsyning i fremtiden, er alt, hvad vi skal gøre, at opdatere Mægler logik; Knap og Ventilator klasser forbliver uberørt.

Dette eksempel viser, hvor let vi kan adskille afhængige objekter og gøre vores system lettere at vedligeholde.

5. Hvornår skal du bruge mediatormønsteret?

Mæglermønsteret er et godt valg, hvis vi skal håndtere et sæt objekter, der er tæt koblet og svære at vedligeholde. På denne måde kan vi reducere afhængighederne mellem objekter og mindske den samlede kompleksitet.

Derudover udvider vi kommunikationslogikken til den enkelte komponent ved hjælp af mediatorobjektet, derfor følger vi princippet om enkelt ansvar. Desuden kan vi introducere nye mæglere uden behov for at ændre de resterende dele af systemet. Derfor følger vi det åben-lukkede princip.

Nogle gange kan vi dog have for mange tætkoblede objekter på grund af systemets defekte design. Hvis dette er tilfældet, bør vi ikke anvende formidlermønsteret. I stedet skal vi tage et skridt tilbage og overveje den måde, vi har modelleret vores klasser på.

Som med alle andre mønstre, Vi er nødt til at overveje vores specifikke brugssag, inden vi blindt implementerer Mediator-mønsteret.

6. Konklusion

I denne artikel lærte vi om formidlermønsteret. Vi forklarede, hvilket problem dette mønster løser, og hvornår vi faktisk skal overveje at bruge det. Vi implementerede også et simpelt eksempel på designmønsteret.

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