S06L18 – Working with composition – Composition continues

More about Composition in Java

Table of Contents

Chapter 1: Introduction to Composition in Java

In object-oriented programming (OOP), one of the essential concepts is composition. Composition allows you to build complex classes by including objects of other classes, forming a “has-a” relationship. This concept helps in modularizing and simplifying code, making it easier to maintain and scale.

In this article, we’ll dive into composition by using a real-world example: a Laptop class that consists of different components like Processor, GraphicsCard, and more. By using this example, we’ll break down how composition works in Java and how it differs from other object-oriented concepts like inheritance.

Chapter 2: What is Composition in Java?

Composition is a design principle in Java that allows an object to contain other objects. It represents a “has-a” relationship between classes. Unlike inheritance, where one class inherits properties and behaviors from a parent class (an “is-a” relationship), composition is more flexible and modular. It promotes the reuse of code by allowing one class to use multiple other classes as components.

For example, consider a laptop: it “has-a” processor, “has-a” graphics card, and “has-a” screen. Each of these components can be modeled as separate classes, and the Laptop class can integrate them through composition.

Key Difference: Composition vs. Inheritance

Aspect Composition Inheritance
Relationship “Has-a” “Is-a”
Coupling Loosely coupled Tightly coupled
Flexibility More flexible Less flexible
Reuse Code reuse through components Code reuse through inheritance
Hierarchy Flat, no hierarchy Hierarchical structure

When to Use Composition?

  • Use composition when you want to model real-world systems that involve parts that can vary independently.
  • Use it when flexibility and loose coupling are more critical than deep class hierarchies.

Chapter 3: Understanding the Laptop Class and Its Components

The Java project we’re working with demonstrates the concept of composition through a Laptop class. The Laptop class is composed of several components:

  • Processor: Represents the laptop’s CPU.
  • GraphicsCard: Represents the GPU.
  • Screen, RAM, Hard Drive, Optical Drive, and Keyboard: Additional attributes that define the laptop’s hardware specifications.

Laptop.java

Chapter 4: Working with Composition in Java: Code Explanation

Let’s look at the Main.java file, where we create and use a Laptop object to demonstrate composition in action.

Main.java

Output Explanation

In this example, the first Laptop object is created using the default constructor, which initializes the processor, graphics card, and other components with default values.

This output shows the default brand of the processor (Intel) as specified in the default constructor of the Processor class.

Next, we create a custom Laptop object using a parameterized constructor, passing custom Processor and GraphicsCard objects.

Chapter 5: Advantages of Using Composition in Java

  • Improved Flexibility: Composition allows you to build systems that are flexible. Unlike inheritance, which creates tightly coupled relationships, composition promotes loose coupling, meaning that objects can function independently of each other.
  • Better Code Reusability: By composing a class with multiple smaller, focused classes, we can reuse these components in other projects or parts of the codebase. For example, the Processor class can be reused across different types of electronic devices, not just laptops.
  • Modular and Scalable: Systems built using composition are more modular. Each component (such as Processor or GraphicsCard) is self-contained and can be updated or modified without affecting the rest of the system.
  • Avoidance of Inheritance Pitfalls: Deep inheritance hierarchies can lead to fragile code that is difficult to maintain and refactor. Composition provides a flatter structure that is easier to extend.

Chapter 6: Conclusion

Composition in Java is a powerful tool for designing complex, flexible, and maintainable applications. Through the example of the Laptop class, we’ve seen how composition promotes code reusability and loose coupling by allowing objects to be built from smaller, focused components. This approach is often preferable to inheritance, particularly in situations where flexibility and modularity are more critical than creating deep class hierarchies.

By using composition effectively, you can create Java applications that are easier to scale, maintain, and extend, making it a vital concept for any Java developer to master.