← Kursa Dön
📄 Text · 10 min

Aggregation ve Association

Association Nedir?

Association, iki sınıf arasındaki genel ilişkidir. Bir sınıfın başka bir sınıfla "bağlantısı" olduğunu ifade eder. Bu, OOP'taki en geniş ilişki kavramı.

Gerçek hayattan düşün: Öğretmen ve Öğrenci arasında bir ilişki var. Öğretmen öğrencileri tanır, öğrenci öğretmenini tanır. Ama biri olmadan diğeri de var olabilir — öğretmen emekli olsa öğrenci hala vardır, öğrenci mezun olsa öğretmen hala vardır. İşte bu bir association.

Association Türleri

Association geniş bir şemsiye, altında üç alt kavram var:

  1. Association — Genel ilişki (uses, knows)

  2. Aggregation — Zayıf sahiplik (HAS-A, parça bağımsız yaşar)

  3. Composition — Güçlü sahiplik (HAS-A, parça bağımsız yaşayamaz)

Bunları bir örnekle açıklayalım:

  • Association: Öğrenci ve Kütüphane — öğrenci kütüphaneyi kullanır

  • Aggregation: Üniversite ve Profesör — profesör üniversiteden ayrılırsa hala yaşar

  • Composition: Ev ve Oda — ev yıkılırsa oda da yok olur

HAS-A İlişkisi

Kalıtım IS-A ilişkisi kurarken, aggregation ve composition HAS-A ilişkisi kurar. "Bir X'in bir Y'si var" cümlesi kurabiliyorsan HAS-A ilişkisi var demektir.

class Department {
    String name;
    List<Employee> employees; // Department HAS employees

    Department(String name) {
        this.name = name;
        this.employees = new ArrayList<>();
    }

    void addEmployee(Employee e) {
        employees.add(e);
    }
}

class Employee {
    String name;

    Employee(String name) {
        this.name = name;
    }
}
Employee ali = new Employee("Ali");
Employee ayse = new Employee("Ayşe");

Department engineering = new Department("Engineering");
engineering.addEmployee(ali);
engineering.addEmployee(ayse);
// Department HAS employees

Department bir Employee değildir (IS-A değil). Ama departmanın çalışanları vardır (HAS-A). Bu ilişki kalıtım ile değil, composition/aggregation ile modellenir.

Aggregation

Aggregation, zayıf bir HAS-A ilişkisidir. "Bütün" yok edilse bile "parçalar" bağımsız olarak yaşamaya devam eder.

class University {
    String name;
    List<Professor> professors;

    University(String name) {
        this.name = name;
        this.professors = new ArrayList<>();
    }

    void hireProfessor(Professor p) {
        professors.add(p);
    }
}

class Professor {
    String name;
    String specialization;

    Professor(String name, String specialization) {
        this.name = name;
        this.specialization = specialization;
    }
}
Professor prof = new Professor("Dr. Yılmaz", "Physics");

University uni1 = new University("ITU");
uni1.hireProfessor(prof);

University uni2 = new University("ODTU");
uni2.hireProfessor(prof); // Aynı profesör iki üniversitede!

Buradaki kilit noktalar:

  1. Professor dışarıda oluşturulup University'ye veriliyor — bağımsız yaşam döngüsü.

  2. Aynı Professor birden fazla University'de olabilir — paylaşılabilir.

  3. University silinse Professor nesnesi hala var — bağımsız yaşar.

Composition

Composition, güçlü bir HAS-A ilişkisidir. "Bütün" yok edilirse "parçalar" da yok olur. Parçaların bağımsız yaşam döngüsü yoktur.

class House {
    List<Room> rooms;

    House(int roomCount) {
        rooms = new ArrayList<>();
        for (int i = 0; i < roomCount; i++) {
            rooms.add(new Room("Room " + (i + 1))); // İçeride oluşturuluyor
        }
    }
}

class Room {
    String name;

    Room(String name) {
        this.name = name;
    }
}
House house = new House(3);
// Room'lar House içinde oluşturuldu
// House silinirse Room'lar da silinir
// Room'lar başka bir House'a ait olamaz

Dikkat et: Room nesneleri House constructor'ı içinde oluşturuluyor. Dışarıdan verilmiyorlar. House garbage collect edilirse, Room nesnelerine başka referans yoksa onlar da collect edilir.

Aggregation vs Composition Karşılaştırma

ÖzellikAggregationComposition
İlişki gücüZayıf (weak)Güçlü (strong)
Yaşam döngüsüBağımsızBağımlı
Parça paylaşımıPaylaşılabilirPaylaşılamaz
Nesne oluşturmaDışarıdaİçeride (genellikle)
Bütün silinirseParça yaşarParça da ölür
UML gösterimBoş elmas (◇)Dolu elmas (◆)

Bir restoranla düşün:

  • Composition: Restoran ve Mutfak — restoran kapanırsa mutfak da kapanır

  • Aggregation: Restoran ve Şef — restoran kapansa şef başka yerde çalışır

UML İlişki Gösterimleri

UML (Unified Modeling Language) sınıf diyagramlarında bu ilişkiler farklı oklarla gösterilir:

Association:     A ------> B        (düz çizgi + ok)
Aggregation:     A ◇-----> B        (boş elmas)
Composition:     A ◆-----> B        (dolu elmas)
Inheritance:     A -----▷ B         (üçgen ok)

Basit bir metin gösterimi:

University ◇--- Professor     (Aggregation)
House ◆--- Room               (Composition)
Dog ---▷ Animal               (Inheritance)
Student ------ Course         (Association)

Gerçekçi Örnek: E-Ticaret Sistemi

Farklı ilişki türlerini bir arada kullanan bir örnek:

// Bağımsız yaşayan sınıflar
class Customer {
    String name;
    String email;

    Customer(String name, String email) {
        this.name = name;
        this.email = email;
    }
}

class Product {
    String name;
    double price;

    Product(String name, double price) {
        this.name = name;
        this.price = price;
    }
}

// OrderItem — Order'a bağımlı (Composition)
class OrderItem {
    Product product;  // Aggregation — ürün bağımsız yaşar
    int quantity;

    OrderItem(Product product, int quantity) {
        this.product = product;
        this.quantity = quantity;
    }

    double getSubtotal() {
        return product.price * quantity;
    }
}

// Order sınıfı
class Order {
    Customer customer;         // Aggregation — müşteri bağımsız
    List<OrderItem> items;     // Composition — item'lar order'a ait
    String orderId;

    Order(String orderId, Customer customer) {
        this.orderId = orderId;
        this.customer = customer;
        this.items = new ArrayList<>();
    }

    void addItem(Product product, int quantity) {
        items.add(new OrderItem(product, quantity)); // İçeride oluştur
    }

    double getTotal() {
        double total = 0;
        for (OrderItem item : items) {
            total += item.getSubtotal();
        }
        return total;
    }
}
Customer ali = new Customer("Ali", "ali@mail.com");
Product laptop = new Product("Laptop", 15000);
Product mouse = new Product("Mouse", 250);

Order order = new Order("ORD-001", ali);
order.addItem(laptop, 1);
order.addItem(mouse, 2);

System.out.println("Total: " + order.getTotal()); // Total: 15500.0

Bu örnekte:

  • OrderCustomer: Aggregation (müşteri siparişten bağımsız yaşar)

  • OrderOrderItem: Composition (sipariş silinirse item'lar da silinir)

  • OrderItemProduct: Aggregation (ürün item'dan bağımsız yaşar)

Kod ile Farkı Nasıl Anlarız?

Aggregation ve composition arasındaki fark Java kodu seviyesinde çok ince olabilir. Ama bazı ipuçları var:

Aggregation belirtileri:

  • Nesne dışarıda oluşturulup constructor/setter ile verilir

  • Aynı nesne birden fazla yerde referans edilebilir

  • null olabilir

class Team {
    List<Player> players; // Dışarıdan veriliyor

    void addPlayer(Player p) {
        players.add(p); // Dışarıda oluşturulmuş nesneyi al
    }
}

Composition belirtileri:

  • Nesne sınıfın içinde oluşturulur

  • Dışarıya referans sızdırılmaz

  • "Sahip" nesne yok edilince parça da yok olur

class Computer {
    CPU cpu;
    RAM ram;

    Computer() {
        this.cpu = new CPU();  // İçeride oluştur
        this.ram = new RAM();  // İçeride oluştur
    }
}

💡 İpucu: Java'da garbage collector bellekle ilgilenir, dolayısıyla "nesne yok olur" kavramı C++ kadar keskin değildir. Ama tasarım niyeti aynıdır — composition'da parçanın bütünsüz bir anlamı yoktur.

Çoklu İlişki Yönelimi

Association'lar tek yönlü veya çift yönlü olabilir:

Tek yönlü (unidirectional):

class Student {
    School school; // Student School'u biliyor

    Student(School school) {
        this.school = school;
    }
}

class School {
    String name;
    // School, Student'ı bilmiyor!
}

Çift yönlü (bidirectional):

class Student {
    School school;
}

class School {
    List<Student> students; // İki taraf da birbirini biliyor
}

Çift yönlü ilişkiler daha karmaşıktır ve senkronizasyon sorunu yaratabilir. Mümkünse tek yönlü tercih et.

⚠️ Dikkat: Çift yönlü ilişkilerde bir tarafı güncellediğinde diğer tarafı da güncellemeni beklenir. Bu "consistency" (tutarlılık) sorunu gerçek projelerde sık karşılaşılan bir problemdir.

Kardinalite (Çokluk)

İlişkilerin kaç nesne içerdiği de önemli:

  • 1:1 — Bir kişinin bir pasaportu var

  • 1:N — Bir departmanın birçok çalışanı var

  • N:M — Bir öğrencinin birçok dersi, bir dersin birçok öğrencisi var

// 1:1
class Person {
    Passport passport;
}

// 1:N
class Department {
    List<Employee> employees;
}

// N:M
class Student {
    List<Course> courses;
}

class Course {
    List<Student> students;
}

Kalıtım, Aggregation, Composition — Hangisi?

Karar verme rehberi:

1. "B bir A mıdır?" → Evet ise: Kalıtım

class Dog extends Animal { } // Dog IS-A Animal ✅

2. "B'nin bir A'sı var mı ve A bağımsız yaşar mı?" → Evet ise: Aggregation

class Library {
    List<Book> books; // Kitaplar bağımsız yaşar
}

3. "B'nin bir A'sı var mı ve A, B'siz anlamsız mı?" → Evet ise: Composition

class Invoice {
    List<InvoiceLine> lines; // Fatura satırı faturasız anlamsız
}

Karmaşık Örnek: Okul Yönetim Sistemi

class Address {
    String city;
    String street;

    Address(String city, String street) {
        this.city = city;
        this.street = street;
    }
}

class Person {
    String name;
    Address address; // Composition — kişiye özel adres

    Person(String name, String city, String street) {
        this.name = name;
        this.address = new Address(city, street);
    }
}

class Teacher extends Person { // IS-A
    String subject;

    Teacher(String name, String city, String street, String subject) {
        super(name, city, street);
        this.subject = subject;
    }
}

class Classroom {
    String roomNumber;
    Teacher teacher;           // Aggregation
    List<Student> students;    // Aggregation

    Classroom(String roomNumber) {
        this.roomNumber = roomNumber;
        this.students = new ArrayList<>();
    }

    void assignTeacher(Teacher t) {
        this.teacher = t;
    }

    void enrollStudent(Student s) {
        students.add(s);
    }
}

Bu örnekte:

  • Teacher IS-A Person → Kalıtım

  • Person HAS-A Address → Composition (adres kişiye ait)

  • Classroom HAS-A Teacher → Aggregation (öğretmen sınıftan bağımsız)

  • Classroom HAS-A Students → Aggregation (öğrenciler sınıftan bağımsız)

⚠️ Dikkat: İlişki türünü belirlerken "bu nesne diğeri olmadan anlamlı mı?" sorusunu sor. Cevap "evet" ise aggregation, "hayır" ise composition.


Özet

  • Association, iki sınıf arasındaki genel ilişkidir; aggregation ve composition bunun alt türleridir.

  • HAS-A ilişkisi bir sınıfın başka bir sınıfı alan olarak içermesidir; IS-A ilişkisinden (kalıtım) farklıdır.

  • Aggregation zayıf sahipliktir — parçalar bağımsız yaşar, paylaşılabilir (Üniversite ◇ Profesör).

  • Composition güçlü sahipliktir — parçalar sahipsiz anlamsızdır, bütünle birlikte yok olur (Ev ◆ Oda).

  • UML'de aggregation boş elmas (◇), composition dolu elmas (◆), kalıtım üçgen ok (▷) ile gösterilir.

  • İlişki seçimi: IS-A → kalıtım, HAS-A + bağımsız → aggregation, HAS-A + bağımlı → composition.