Komposisi, Gabungan, dan Gabungan di Jawa

1. Pengenalan

Objek mempunyai hubungan antara keduanya, baik dalam kehidupan nyata maupun dalam pengaturcaraan. Kadang kala sukar untuk memahami atau melaksanakan hubungan ini.

Dalam tutorial ini, kita akan memfokuskan pada pengambilan Java pada tiga jenis hubungan yang kadang-kadang mudah dicampur: komposisi, gabungan, dan pergaulan.

2. Komposisi

Komposisi adalah jenis hubungan "kepunyaan". Ini bermaksud bahawa salah satu objek adalah struktur yang lebih besar secara logik, yang mengandungi objek lain. Dengan kata lain, ia adalah bahagian atau anggota objek lain.

Sebagai alternatif, kita sering menyebutnya hubungan "has-a" (berbanding hubungan "is-a", yang merupakan warisan).

Contohnya, bilik milik bangunan, atau dengan kata lain bangunan mempunyai bilik. Jadi pada dasarnya, sama ada kita menyebutnya "kepunyaan" atau "has-a" hanyalah masalah.

Komposisi adalah jenis hubungan "has-a" yang kuat kerana objek yang mengandunginya memilikinya. Oleh itu, kitaran hidup objek diikat. Ini bermaksud bahawa jika kita memusnahkan objek pemiliknya, anggotanya juga akan musnah dengannya. Sebagai contoh, bilik itu musnah dengan bangunan seperti contoh sebelumnya.

Perhatikan itu tidak bermaksud, bahawa objek yang berisi tidak boleh wujud tanpa ada bahagiannya. Sebagai contoh, kita dapat merobohkan semua dinding di dalam bangunan, sehingga menghancurkan bilik. Tetapi bangunan itu akan tetap ada.

Dari segi kardinaliti, objek yang berisi boleh memiliki seberapa banyak bahagian yang kita mahukan. Walau bagaimanapun, semua bahagian mesti mempunyai satu bekas .

2.1. UML

Di UML, kami menunjukkan komposisi dengan simbol berikut:

Perhatikan, bahawa berlian berada di objek yang mengandung dan merupakan dasar garis, bukan kepala panah. Demi kejelasan, kami juga sering menggunakan anak panah:

Oleh itu, kita boleh menggunakan konstruk UML ini untuk contoh Bangunan-Bilik kami:

2.2. Kod sumber

Di Jawa, kita dapat memodelkannya dengan kelas dalaman yang tidak statik:

class Building { class Room {} }

Sebagai alternatif, kita boleh menyatakan kelas itu dalam badan kaedah juga. Tidak kira sama ada kelas bernama, kelas tanpa nama atau lambda:

class Building { Room createAnonymousRoom() { return new Room() { @Override void doInRoom() {} }; } Room createInlineRoom() { class InlineRoom implements Room { @Override void doInRoom() {} } return new InlineRoom(); } Room createLambdaRoom() { return () -> {}; } interface Room { void doInRoom(); } }

Perhatikan, bahawa penting, kelas dalaman kita tidak statik kerana mengikat semua keadaannya ke kelas yang mengandungi.

Biasanya, objek yang mengandungi ingin mengakses anggotanya. Oleh itu, kita harus menyimpan rujukan mereka:

class Building { List rooms; class Room {} }

Perhatikan, bahawa semua objek kelas dalaman menyimpan rujukan tersirat ke objek yang mengandunginya. Akibatnya, kami tidak perlu menyimpannya secara manual untuk mengaksesnya:

class Building { String address; class Room { String getBuildingAddress() { return Building.this.address; } } }

3. Pengumpulan

Agregasi juga merupakan hubungan "has-a". Apa yang membezakannya dari komposisi, itu tidak melibatkan pemilikan. Akibatnya, kitaran hidup objek tidak terikat: setiap satu daripadanya dapat wujud secara bebas antara satu sama lain.

Contohnya, sebuah kereta dan roda. Kita boleh melepaskan roda, dan mereka masih ada. Kita boleh memasang roda lain (yang sudah ada), atau memasangkannya ke kereta lain dan semuanya akan berjalan lancar.

Sudah tentu, kereta tanpa roda atau roda yang terpisah tidak akan berguna seperti kereta dengan roda dihidupkan. Tetapi itulah sebabnya hubungan ini wujud sejak awal: untuk menyusun bahagian-bahagian ke bentuk yang lebih besar, yang mampu lebih banyak perkara daripada bahagiannya .

Oleh kerana penggabungan tidak melibatkan pemilikan, ahli tidak perlu terikat dengan satu bekas sahaja . Contohnya, segitiga diperbuat daripada segmen. Tetapi segitiga boleh berkongsi segmen sebagai sisi mereka.

3.1. UML

Agregasi sangat serupa dengan komposisi. Satu-satunya perbezaan logik adalah agregasi adalah hubungan yang lebih lemah.

Oleh itu, representasi UML juga serupa. Satu-satunya perbezaan adalah berlian kosong:

Oleh itu, untuk kereta dan roda, kami akan melakukan:

3.2. Kod sumber

Di Jawa, kita dapat memodelkan agregasi dengan rujukan lama yang jelas:

class Wheel {} class Car { List wheels; }

Ahli boleh menjadi jenis kelas apa pun, kecuali kelas dalaman yang tidak statik.

Dalam coretan kod di atas kedua-dua kelas mempunyai fail sumbernya yang berasingan. Walau bagaimanapun, kita juga boleh menggunakan kelas dalaman yang statik:

class Car { List wheels; static class Wheel {} }

Perhatikan bahawa Java akan membuat rujukan tersirat hanya dalam kelas dalaman yang tidak statik. Oleh kerana itu, kita harus menjaga hubungan secara manual di mana kita memerlukannya:

class Wheel { Car car; } class Car { List wheels; }

4. Persatuan

Pergaulan adalah hubungan yang paling lemah antara mereka bertiga. Ini bukan hubungan "has-a" , tidak ada objek yang menjadi bahagian atau anggota yang lain.

Pergaulan hanya bermaksud bahawa objek "saling mengenal" satu sama lain. Contohnya, seorang ibu dan anaknya.

4.1. UML

Di UML, kita dapat menandakan hubungan dengan anak panah:

Sekiranya hubungan itu dua arah, kita dapat menggunakan dua anak panah, panah dengan kepala panah di kedua ujungnya, atau garis tanpa kepala panah:

We can represent a mother and her child in UML, then:

4.2. Source Code

In Java, we can model association the same way as aggregation:

class Child {} class Mother { List children; }

But wait, how can we tell if a reference means aggregation or association?

Well, we can't. The difference is only logical: whether one of the objects is part of the other or not.

Also, we have to maintain the references manually on both ends as we did with aggregation:

class Child { Mother mother; } class Mother { List children; }

5. UML Sidenote

For the sake of clarity, sometimes we want to define the cardinality of a relationship on a UML diagram. We can do this by writing it to the ends of the arrow:

Note, that it doesn't make sense to write zero as cardinality, because it means there's no relationship. The only exception is when we want to use a range to indicate an optional relationship:

Also note, that since in composition there's precisely one owner we don't indicate it on the diagrams.

6. A Complex Example

Let's see a (little) more complex example!

We'll model a university, which has its departments. Professors work in each department, who also has friends among each other.

Will the departments exist after we close the university? Of course not, therefore it's a composition.

But the professors will still exist (hopefully). We have to decide which is more logical: if we consider professors as parts of the departments or not. Alternatively: are they members of the departments or not? Yes, they are. Hence it's an aggregation. On top of that, a professor can work in multiple departments.

Hubungan antara profesor adalah pergaulan kerana tidak masuk akal untuk mengatakan bahawa seorang profesor adalah bahagian yang lain.

Hasilnya, kita dapat memodelkan contoh ini dengan rajah UML berikut:

Dan kod Java kelihatan seperti ini:

class University { List department; } class Department { List professors; } class Professor { List department; List friends; }

Perhatikan, bahawa jika kita bergantung pada istilah "has-a", "kepunyaan", "member-of", "part-of" , dan sebagainya, kita dapat mengenal pasti hubungan antara objek kita dengan lebih mudah.

7. Kesimpulannya

Dalam artikel ini, kami melihat sifat dan gambaran komposisi, penggabungan, dan perkaitan. Kami juga melihat bagaimana memodelkan hubungan tersebut di UML dan Java.

Seperti biasa, contohnya terdapat di GitHub.