Aggregation in Java

Aggregation is a term which is used to refer one way relationship between two objects. It is a form of HAS-A relationship between two classes. Aggregation in Java allows us to provide a reference for one class within another class.

We should not confuse aggregation with Inheritance. Aggregation is a type of association between two classes where one class contains a reference to another class, typically as part of its attributes. This relationship represents a "whole-part" association, where the containing class is composed of objects from the contained class. Unlike inheritance, which signifies an "is-a" relationship, aggregation signifies a "has-a" relationship.


Use Cases of Aggregation

  • Modeling Collections : Aggregation is commonly used to model collections of objects within a larger entity. For example, a Library can aggregate a collection of Book objects, a Department can aggregate a list of Employee objects, etc.
    class Department {
        private String departmentName;
        // Aggregation: Department has-a Employee
        private Employee[] employees; 
    }
    

  • Composite Objects : Aggregation is useful for creating composite objects that consist of multiple components. Each component can be represented by a separate class, and the composite object can aggregate these components.
    class Car {
        private Engine engine; // Aggregation: Car has-a Engine
        private Wheel[] wheels; // Aggregation: Car has-many Wheel
        // Other components
    }
    

  • Managing Relationships : Aggregation is valuable for managing relationships between objects when the relationship is more of a "has-a" nature than an "is-a" nature. For instance, a Company may aggregate a list of Employee objects, indicating that the company has employees.
    class Company {
        private String companyName;
        // Aggregation: Company has-many Employee
        private Employee[] employees; 
    }
    

Aggregation vs. Composition

Aggregation and composition are closely related concepts, but they differ in the lifecycle and ownership of the contained objects.
  • Aggregation : In aggregation, the contained objects have an independent lifecycle and can exist outside the scope of the containing object. For example, a University may contain Student objects, but these students can exist independently of the university.

  • Composition : In composition, the contained objects are owned by the containing object, and their lifecycle is tightly bound to the containing object. If the containing object is destroyed, the contained objects are also destroyed. This is a more stringent relationship than aggregation.

Real life examples of aggregation(has-a relationship)

  1. A Bus has a steering wheel but vice versa is not possible and thus it is unidirectional in nature.

  2. A Manager object contains many informations such as name, emailId etc. It contains one more object named address, which contains its own informations such as city, state etc. Manager object contains a reference of Address object, so relationship is Manager HAS-A address.
class Address {
   String city;
   String state;
   ...
}

class Manager {
   String name;
   String emialId;
   Address address; 
}

Java program for aggregation relationship

class Address {
  String city;
  String state;
	String zipcode;

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

  @Override
  public String toString() {
    return String.format("%s, %s, %s", city, state, zipcode);
  }
}

// Manager has an Address reference
class Manager {
  Manager(String name, String emialId, Address address) {
    this.name = name;
    this.emialId = emialId;
    this.address = address;
  }

  String name;
  String emialId;
  // Has-A relationship
  Address address;
}

public class AggregationJava {
  public static void main(String[] args) {
    Address address = new Address("Miami", "Florida", "12345" );
    Manager manager = new Manager("John", "abc@gmail,com", address);

    // Printing Manager Address
    System.out.println(manager.address.toString());
  }
}
Output
Miami, Florida, 12345

The above program, shows the Aggregation between Manager and Address classes. You can see that Manager class contains a property of type Address to obtain manager's address. Its a typical example of Aggregation(Has-A) relationship in Java.


Best Practices and Considerations for Aggregation

  • Encapsulation : Encapsulation remains a fundamental principle in OOP. Ensure that the internal details of the aggregated class are encapsulated, and access to its state is controlled through methods. This maintains a clean separation between the containing class and the contained class.

  • Lifecycle Management : Understand the lifecycle implications of aggregation. In aggregation, the contained objects have independent lifecycles. Be mindful of object creation, deletion, and potential scenarios where the containing object may outlive the contained objects.

  • Immutable Classes : Consider making the contained objects immutable, especially if they represent value objects. This ensures that the state of the aggregated objects cannot be changed externally, promoting a more predictable and maintainable design.

  • Avoid Deep Aggregation Hierarchies : Similar to deep inheritance hierarchies, deep aggregation hierarchies can make the code harder to understand and maintain. Strive for a balanced and meaningful aggregation structure.

  • UML Notation for Aggregation : In Unified Modeling Language (UML), aggregation is represented by a hollow diamond shape on the side of the containing class. Understanding and using UML notation can enhance the clarity of your design.

Conclusion

Aggregation is a powerful concept in Java that allows for the creation of complex, modular, and flexible systems. By understanding the principles of aggregation and applying best practices, developers can design code that is both maintainable and adaptable. Whether modeling collections, composite objects, or managing relationships, aggregation provides a valuable tool for building robust object-oriented systems.