Zloženie, agregácia a združenie v Jave

1. Úvod

Objekty majú medzi sebou vzťahy, tak v reálnom živote, ako aj v programovaní. Niekedy je ťažké pochopiť alebo implementovať tieto vzťahy.

V tomto tutoriáli sa zameriame na to, ako Java využíva tri niekedy ľahko zmiešané typy vzťahov: zloženie, agregácia a asociácia.

2. Zloženie

Zloženie je vzťah typu „patrí“. Znamená to, že jeden z objektov je logicky väčšia štruktúra, ktorá obsahuje druhý objekt. Inými slovami, je súčasťou alebo členom druhého objektu.

Prípadne často to nazývame vzťahom „má“ (na rozdiel od vzťahu „je-a“, ktorý je dedičstvom).

Napríklad miestnosť patrí k budove, alebo inými slovami, budova má izbu. Takže v podstate to, či to nazveme „patrí“, alebo „má-a“, je iba otázkou uhla pohľadu.

Kompozícia je silným druhom vzťahu „má-a“, pretože ho vlastní obsahujúci objekt. Preto životné cykly objektov sú viazané. Znamená to, že ak zničíme objekt vlastníka, zničia sa s ním aj jeho členovia. Napríklad miestnosť je zničená budovou v našom predchádzajúcom príklade.

To neznamená, že obsahujúci objekt nemôže existovať bez ktorejkoľvek z jeho častí. Napríklad môžeme zbúrať všetky steny vo vnútri budovy, a tak zničiť miestnosti. Budova ale bude stále existovať.

Z hľadiska mohutnosti môže mať obsahujúci objekt toľko častí, koľko chceme. Avšak všetky časti musia mať presne jednu nádobu.

2.1. UML

V UML označujeme zloženie nasledujúcim symbolom:

Všimnite si, že diamant je pri obsahujúcom objekte a je základom čiary, nie hrotom šípky. Kvôli prehľadnosti často nakreslíme aj šípku:

Takže potom môžeme použiť tento UML konštrukt pre náš príklad Building-Room:

2.2. Zdrojový kód

V Jave to môžeme modelovať s nestatickou vnútornou triedou:

budova triedy {miestnosť triedy {}}

Prípadne môžeme túto triedu vyhlásiť aj v tele metódy. Nezáleží na tom, či ide o pomenovanú triedu, anonymnú triedu alebo lambdu:

budova triedy {Room createAnonymousRoom () {return new Room () {@Override void doInRoom () {}}; } Izba createInlineRoom () {trieda InlineRoom implementuje miestnosť {@Override void doInRoom () {}} vrátiť nový InlineRoom (); } Izba createLambdaRoom () {return () -> {}; } rozhranie Room {void doInRoom (); }}

Upozorňujeme, že je nevyhnutné, aby naša vnútorná trieda bola nestatická, pretože viaže všetky svoje inštancie na triedu obsahujúcu.

Zvyčajne obsahujúci objekt chce získať prístup k svojim členom. Preto by sme si mali uložiť ich referencie:

budova triedy {Zoznam miestností; miestnosť triedy {}}

Upozorňujeme, že všetky objekty vnútornej triedy ukladajú implicitný odkaz na ich obsahujúci objekt. Vo výsledku ho kvôli prístupu nemusíme ukladať manuálne:

budova triedy {Adresa reťazca; trieda Izba {String getBuildingAddress () {návrat Building.this.address; }}}

3. Agregácia

Agregácia je tiež vzťahom „má“. To, čo ho odlišuje od zloženia, že nezahŕňa vlastníctvo. Výsledkom je, že životné cykly objektov nie sú viazané: každý z nich môže existovať nezávisle na sebe.

Napríklad auto a jeho kolesá. Môžeme zložiť kolesá a stále budú existovať. Môžeme namontovať ďalšie (už existujúce) kolesá alebo ich nainštalovať do iného automobilu a všetko bude fungovať dobre.

Auto bez kolies alebo odpojené koleso samozrejme nebude také užitočné ako auto so zapnutými kolesami. Ale preto tento vzťah existoval na prvom mieste: k zhromaždiť diely k väčšej konštrukcii, ktorá je schopná viac vecí ako jej časti.

Pretože agregácia nezahŕňa vlastníctvo, člen nemusí byť viazaný iba na jeden kontajner. Napríklad trojuholník je vyrobený zo segmentov. Ale trojuholníky môžu zdieľať segmenty ako svoje strany.

3.1. UML

Agregácia je veľmi podobná zloženiu. Jediným logickým rozdielom je agregácia - slabší vzťah.

Preto sú reprezentácie UML tiež veľmi podobné. Jediný rozdiel je, že diamant je prázdny:

Pre autá a kolesá by sme teda robili:

3.2. Zdrojový kód

V Jave môžeme modelovať agregáciu s obyčajným starým odkazom:

trieda Koleso {} trieda Auto {Zoznam kolies; }

Členom môže byť akýkoľvek typ triedy, okrem nestatickej vnútornej triedy.

V útržku kódu vyššie majú obe triedy svoj samostatný zdrojový súbor. Môžeme však použiť aj statickú vnútornú triedu:

trieda Auto {Zoznam kolies; koleso statickej triedy {}}

Upozorňujeme, že Java vytvorí implicitný odkaz iba v nestatických vnútorných triedach. Z tohto dôvodu musíme vzťah udržiavať manuálne tam, kde to potrebujeme:

trieda Koleso {Auto; } trieda Auto {Zoznam kolies; }

4. Združenie

Asociácia je najslabší vzťah medzi týmito tromi. Nie je to vzťah „má“, žiadny z objektov nie je časťou alebo členom iného.

Združenie znamená iba to, že sa objekty navzájom „poznajú“. Napríklad matka a jej dieťa.

4.1. UML

V UML môžeme označiť asociáciu šípkou:

Ak je asociácia obojsmerná, môžeme použiť dve šípky, šípku s hrotom šípu na oboch koncoch alebo čiaru bez hrotov šípok:

Matku a jej dieťa môžeme zastupovať v UML, potom:

4.2. Zdrojový kód

V Jave môžeme modelovať asociáciu rovnakým spôsobom ako agregáciu:

trieda Dieťa {} trieda Matka {Zoznam detí; }

Ale počkaj, ako môžeme zistiť, či referencia znamená agregáciu alebo asociáciu?

No nemôžeme. Rozdiel je iba logický: či je jeden z objektov súčasťou druhého alebo nie.

Musíme tiež udržiavať odkazy manuálne na oboch koncoch, ako sme to robili pri agregácii:

trieda Dieťa {Matka matka; } trieda Matka {Zoznam detí; }

5. UML Sidenote

Kvôli prehľadnosti niekedy chceme definovať mohutnosť vzťahu na UML diagrame. Môžeme to urobiť tak, že to napíšeme na konce šípky:

Upozorňujeme, že nemá zmysel písať nulu ako mohutnosť, pretože to znamená, že neexistuje žiadny vzťah. Jedinou výnimkou je prípad, keď chceme pomocou rozsahu označiť voliteľný vzťah:

Upozorňujeme tiež, že keďže v zložení je presne jeden vlastník, neuvádzame to na diagramoch.

6. Zložitý príklad

Pozrime sa na (trochu) zložitejší príklad!

Budeme modelovať univerzitu, ktorá má svoje katedry. Na každom oddelení pracujú profesori, ktorí majú medzi sebou aj priateľov.

Budú oddelenia existovať aj po zatvorení univerzity? Samozrejme, že nie, preto je to zloženie.

Profesori ale budú (dúfajme) stále existovať. Musíme sa rozhodnúť, čo je logickejšie: ak budeme profesorov považovať za súčasť katedier alebo nie. Prípadne: sú členmi katedier alebo nie? Áno sú. Preto je to agregácia. Okrem toho môže profesor pracovať na viacerých oddeleniach.

Vzťah medzi profesormi je asociácia, pretože nemá zmysel tvrdiť, že profesor je súčasťou iného.

Vo výsledku môžeme tento príklad modelovať pomocou nasledujúceho diagramu UML:

A kód Java vyzerá takto:

trieda Univerzita {Zoznam katedier; } triedna katedra {Zoznam profesorov; } triedny profesor {oddelenie List; Zoznam priateľov; }

Upozorňujeme, že ak spoliehať sa na výrazy „má-a“, „patrí-do“, „člen-člena“, „súčasť“, a tak ďalej, môžeme ľahšie identifikovať vzťahy medzi našimi objektmi.

7. Záver

V tomto článku sme videli vlastnosti a zastúpenie zloženia, agregácie a asociácie. Tiež sme videli, ako modelovať tieto vzťahy v UML a Java.

Ako obvykle sú príklady k dispozícii na GitHub.


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