Composition in Java with Examples

The composition is a restricted form of Aggregation in which two entities are highly dependent on each other.

It represents the part-of relationship.

In composition, both the entities are dependent on each other.

When there is a composition between two entities, the composed object cannot exist without the other entity.

We should know :

The composition is easily achieved at runtime while inheritance provides its features at compile time.

The Composition is also known as HAS-A relation and Inheritance is also known as IS-A relation.

It enables a group of objects that have to be treated in the same way as a single instance of an object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies.

Consider the following Composition Example

Key Participants:

Component:

Is the abstraction for all components, including composite ones Declares the interface for objects in the composition.Part,getPrice() ,getName()

Engine:

Represents child objects in the composition Implements all Component methods.eg.Engine,Trunk,Body etc.

Composite:

Represents a composite Component (component having children) Implement methods to manipulate children. Implements all Component methods, generally by delegating them to its children.eg.Car, Tempo, etc

We have the Part interface as the prototype

package com.javacodestuffs.core.object.oriented.concepts.composition; import java.util.List; import java.util.ArrayList; interface Part { public double getPrice(); public String getName(); }

We have Engine.java as

package com.javacodestuffs.core.object.oriented.concepts.composition; class Engine implements Part { String name; double price; public Engine(String name, double price) { this.name = name; this.price = price; } public double getPrice() { return price; } public String getName() { return name; } }

We have Trunk.java

package com.javacodestuffs.core.object.oriented.concepts.composition; class Trunk implements Part { String name; double price; public Trunk(String name, double price) { this.name = name; this.price = price; } public double getPrice() { return price; } public String getName() { return name; } }

We have Body.java

package com.javacodestuffs.core.object.oriented.concepts.composition; class Body implements Part { String name; double price; public Body(String name, double price) { this.name = name; this.price = price; } public double getPrice() { return price; } public String getName() { return name; } }

We have Tempo.java

package com.javacodestuffs.core.object.oriented.concepts.composition; class Tempo implements Part { List < Part > parts; String name; public Tempo(String name) { this.name = name; parts = new ArrayList < Part > (); } public void addPart(Part part) { parts.add(part); } public String getName() { return name; } public String getPartNames() { StringBuilder sb = new StringBuilder(); for (Part part: parts) { sb.append(part.getName()).append(" "); } return sb.toString(); } public double getPrice() { double price = 0; for (Part part: parts) { price += part.getPrice(); } return price; } }

we have Car.java

package com.javacodestuffs.core.object.oriented.concepts.composition; class Car implements Part { List < Part > parts; String name; public Car(String name) { this.name = name; parts = new ArrayList < Part > (); } public void addPart(Part part) { parts.add(part); } public String getName() { return name; } public String getPartNames() { StringBuilder sb = new StringBuilder(); for (Part part: parts) { sb.append(part.getName()).append(" "); } return sb.toString(); } public double getPrice() { double price = 0; for (Part part: parts) { price += part.getPrice(); } return price; } }

we have CompositeExampleTest.java

package com.javacodestuffs.core.object.oriented.concepts.composition; public class CompositeExampleTest{ public static void main(String args[]) { Part carEngine = new Engine("Disel Engine", 15000); Part carTrunk = new Trunk("Trunk", 10000); Part carBody = new Body("Body", 12000); Car car = new Car("Innova"); car.addPart(carEngine); car.addPart(carTrunk); car.addPart(carBody); System.out.println("\nCar Details are : "); System.out.println("Car name : " + car.getName()); System.out.println("Car parts : " + car.getPartNames()); System.out.println("Car price : " + car.getPrice()); Part tempoEngine = new Engine("Disel Engine", 20000); Part tempoTrunk = new Trunk("Trunk", 19000); Part tempoBody = new Body("Body", 350000); Tempo tempo = new Tempo("Mahindra Jeeto"); tempo.addPart(tempoEngine); tempo.addPart(tempoTrunk); tempo.addPart(tempoBody); System.out.println("\nTempo Details are : "); System.out.println("Tempo name : " + tempo.getName()); System.out.println("Tempo parts : " + tempo.getPartNames()); System.out.println("Tempo price : " + tempo.getPrice()); } } output: Car Details are : Car name : Innova Car parts : Disel Engine Trunk Body Car price : 37000.0 Tempo Details are : Tempo name : Mahindra Jeeto Tempo parts : Disel Engine Trunk Body Tempo price : 389000.0

Explanation:

1). The Part is a prototype.

2). Car, Tempo contains many Parts.

3). Different Parts of the car have been added to Car.

4). The price of Car = sum of ( Price of each Part ).

Java Composition Benefits

1). The Program for composition in java is not affected by any change in the Engine object.

2). If you are looking for code reuse and the relationship between the two classes is has-a then you should use composition rather than inheritance.

3). We can control the visibility of other objects to client classes and reuse only what we need.

4). If there change in the other class implementation, for example, getPrice() returning long, we need to change Part class to accommodate it but the client class not needed any change.

Composition allows the creation of back-end class when it's required at runtime.

In this article, we have seen Composition in Java with Examples. All source code in the article can be found in the GitHub repository.