A közvetítő minta Java-ban

1. Áttekintés

Ebben a cikkben megnézzük a Mediator Pattern, a GoF egyik viselkedési mintája. Leírjuk a célját, és elmagyarázzuk, mikor kell használnunk.

Szokás szerint egy egyszerű példát is megadunk.

2. Közvetítő minta

Az objektumorientált programozás során mindig meg kell próbálnunk úgy tervezze meg a rendszert, hogy az alkatrészek lazán összekapcsolódjanak és újrafelhasználhatók legyenek. Ez a megközelítés megkönnyíti kódunk karbantartását és tesztelését.

A való életben azonban gyakran függő tárgyak komplex halmazával kell megküzdenünk. Ekkor jöhet jól a közvetítő minta.

A közvetítő minta célja a szorosan összekapcsolt, közvetlenül egymással kommunikáló objektumok közötti bonyolultság és függőség csökkentése. Ez egy olyan közvetítő objektum létrehozásával érhető el, amely gondoskodik a függő objektumok közötti interakcióról. Következésképpen az összes kommunikáció a közvetítőn keresztül zajlik.

Ez elősegíti a laza összekapcsolódást, mivel az együtt működő alkatrészeknek már nem kell közvetlenül kölcsönhatásba lépniük. Ehelyett csak az egyetlen közvetítő objektumra hivatkoznak. Így könnyebb ezeket az objektumokat újból felhasználni a rendszer más részeiben.

3. A mediátor minta UML-diagramja

Most nézzük meg a mintát vizuálisan:

A fenti UML diagramban a következő résztvevőket azonosíthatjuk:

  • Közvetítő meghatározza az interfészt a Kolléga az objektumok kommunikációra használják
  • Kolléga meghatározza az absztrakt osztályt, amely egyetlen hivatkozást tartalmaz a Közvetítő
  • BetonKözvetítő az interakciós logikát foglalja magában Kolléga tárgyakat
  • BetonKolléga1 és BetonKolléga2 csak a Közvetítő

Ahogy látjuk, Kolléga az objektumok nem utalnak közvetlenül egymásra. Ehelyett az összes kommunikációt a Közvetítő.

Következésképpen, BetonKolléga1 és BetonKolléga2 könnyebben újrafelhasználható.

Továbbá abban az esetben, ha változtatnunk kell a módján Kolléga objektumok együtt működnek, csak a BetonKözvetítő logika. Vagy létrehozhatunk egy új megvalósítást a Közvetítő.

4. Java implementáció

Most, hogy világos elképzelésünk van az elméletről, nézzünk meg egy példát, hogy jobban megértsük a koncepciót a gyakorlatban.

4.1. Példa forgatókönyv

Képzelje el, hogy egy egyszerű hűtőrendszert építünk, amely ventilátorból, tápegységből és egy gombból áll. A gomb megnyomásával vagy be- vagy kikapcsolja a ventilátort. Mielőtt bekapcsolnánk a ventilátort, be kell kapcsolnunk az áramellátást. Hasonlóképpen, a ventilátor kikapcsolása után azonnal ki kell kapcsolnunk az áramot.

Vessünk egy pillantást a megvalósítás példájára:

nyilvános osztály Gomb {privát rajongói rajongó; // konstruktor, getterek és beállítók public void press () {if (fan.isOn ()) {fan.turnOff (); } else {fan.turnOn (); }}}
nyilvános osztály Fan {private Button gomb; privát PowerSupplier powerSupplier; privát logikai isOn = hamis; // konstruktor, getterek és beállítók public void turnOn () {powerSupplier.turnOn (); isOn = igaz; } public void turnOff () {isOn = hamis; powerSupplier.turnOff (); }}
public class PowerSupplier {public void turnOn () {// implementáció} public void turnOff () {// implementáció}}

Ezután teszteljük a funkcionalitást:

@Test public void givenTurnedOffFan_whenPressingButtonTwice_fanShouldTurnOnAndOff () {assertFalse (fan.isOn ()); gomb.nyomás (); assertTrue (fan.isOn ()); gomb.nyomás (); assertFalse (fan.isOn ()); }

Úgy tűnik, minden rendben működik. De vedd észre, hogyan Gomb, rajongó, és PowerSupplier osztályok szorosan összekapcsolódnak. A Gomb közvetlenül a Ventilátor és a Ventilátor kölcsönhatásba lép mindkettővel Gomb és PowerSupplier.

Nehéz lenne újból felhasználni a Gomb osztály más modulokban. Továbbá, ha hozzá kell adnunk egy második tápegységet a rendszerünkhöz, akkor módosítanunk kellene a Ventilátor osztály logikája.

4.2. A közvetítő minta hozzáadása

Most valósítsuk meg a Mediátor mintát az osztályaink közötti függőségek csökkentése és a kód újrafelhasználhatósága érdekében.

Először mutassuk be a Közvetítő osztály:

nyilvános osztály Közvetítő {privát Gomb gomb; saját ventilátor ventilátor; privát PowerSupplier powerSupplier; // konstruktor, getterek és beállítók public void press () {if (fan.isOn ()) {fan.turnOff (); } else {fan.turnOn (); }} public void start () {powerSupplier.turnOn (); } public void stop () {powerSupplier.turnOff (); }}

Ezután módosítsuk a többi osztályt:

nyilvános osztály Gomb {magánközvetítő közvetítő; // konstruktor, getterek és beállítók public void press () {mediator.press (); }}
nyilvános osztály Fan {magánközvetítő közvetítő; privát logikai isOn = hamis; // konstruktor, getterek és beállítók public void turnOn () {mediator.start (); isOn = igaz; } public void turnOff () {isOn = hamis; közvetítő.stop (); }}

Ismét teszteljük a funkcionalitást:

@Test public void givenTurnedOffFan_whenPressingButtonTwice_fanShouldTurnOnAndOff () {assertFalse (fan.isOn ()); gomb.nyomás (); assertTrue (fan.isOn ()); gomb.nyomás (); assertFalse (fan.isOn ()); }

Hűtőrendszerünk a várakozásoknak megfelelően működik.

Most, hogy megvalósítottuk a Közvetítő mintát, egyik sem Gomb, Ventilátor, vagy PowerSupplier osztályok közvetlenül kommunikálnak. Csak egyetlen hivatkozásuk van a Közvetítő.

Ha a jövőben hozzá kell adnunk egy második tápegységet, csak frissítenünk kell Közvetítő logika; Gomb és Ventilátor osztályok érintetlenek maradnak.

Ez a példa megmutatja, hogy milyen könnyen tudjuk elkülöníteni a függő objektumokat, és megkönnyítjük a rendszerünk karbantartását.

5. Mikor használja a közvetítő mintát

A közvetítő minta jó választás, ha szorosan összekapcsolt és nehezen karbantartható tárgyakkal kell megküzdenünk. Így csökkenthetjük az objektumok közötti függőségeket és csökkenthetjük a teljes komplexitást.

Ezenkívül a mediátor objektum használatával kibontjuk a kommunikációs logikát az egyetlen komponensbe, ezért követjük az egységes felelősség elvét. Ezenkívül új közvetítőket is bevezethetünk, anélkül, hogy a rendszer többi részét meg kellene változtatni. Ezért követjük a nyitott-zárt elvet.

Előfordulhat azonban, hogy a rendszer hibás kialakítása miatt túl sok szorosan összekapcsolt objektumunk van. Ebben az esetben nem alkalmazhatjuk a közvetítő mintát. Ehelyett egy lépést kell visszalépnünk, és újragondolnunk az osztályok modellezésének módját.

Mint minden más mintában, meg kell fontolnunk sajátos felhasználási esetünket, mielőtt vakon megvalósítanánk a közvetítő mintát.

6. Következtetés

Ebben a cikkben megtudtuk a közvetítő mintát. Elmagyaráztuk, hogy ez a minta milyen problémát old meg, és mikor érdemes megfontolnunk a használatát. A tervezési minta egyszerű példáját is megvalósítottuk.

Mint mindig, a teljes kódminták elérhetők a GitHubon.


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