Definition
Beyond the four pillars, OOP includes three relationship concepts that describe how objects collaborate.
- Association is the most general relationship: object A uses object B, both exist independently (
TradeServiceusesNotificationService). - Aggregation is a weak HAS-A relationship: the parent has children, but children can exist independently (
BranchhasEmployeeobjects that survive if the branch closes). - Composition is a strong OWNS-A relationship: the parent owns children, and children cannot exist without the parent (
AccountownsTransactionrecords that are deleted when the account is closed). - Modularity means each class is a self-contained unit that can be developed and tested independently.
- Maintainability means changing one class does not break others.
- Real-world modeling means bank accounts, trades, and customers map naturally to objects.
At National Bank of India, all seven concepts coexist. Rajesh's account balance is private (encapsulation). Transfer hides 15 steps (abstraction). SavingsAccount extends Account (inheritance). calculateInterest() returns different results per type (polymorphism). TradeService uses MarketDataProvider (association). TradingDepartment has Traders who survive if the department closes (aggregation). Account owns Transactions that are deleted when the account closes (composition).
Understanding the Concepts
What are all seven OOP concepts?
The four pillars (encapsulation, abstraction, inheritance, polymorphism) define how individual classes are built. The three relationship concepts (association, aggregation, composition) define how objects collaborate. Together they form a complete picture of object-oriented design.
What is association?
Association is the most general relationship between two objects. Object A knows about object B and can call its methods. Neither owns the other. Both have independent lifecycles. In Java, one class holds a reference to another, typically through a field or constructor parameter.
package com.bank.service;
public class TradeService {
private final NotificationService notificationService; // association: uses
public TradeService(NotificationService notificationService) {
this.notificationService = notificationService;
// TradeService does not CREATE notificationService: it is injected.
}
public void executeTrade(Trade trade) {
// ... execute trade logic ...
notificationService.sendTradeConfirmation(trade);
}
}
// TradeService and NotificationService are associated.
// Neither owns the other. Spring injects the dependency.
What is aggregation?
Aggregation is a weak HAS-A relationship. The parent contains children, but children have independent lifecycles. They can exist without the parent. If the parent is destroyed, children survive.
package com.bank.model;
import java.util.ArrayList;
import java.util.List;
public class TradingDepartment {
private String departmentName;
private List<Trader> traders = new ArrayList<>();
public void addTrader(Trader trader) {
traders.add(trader);
// Department does NOT create the trader.
}
public List<Trader> dissolve() {
List<Trader> surviving = new ArrayList<>(traders);
traders.clear();
return surviving; // traders still exist, can join another department
}
}
// department = null; traders still exist in memory.
// In JPA: NO cascade delete.
What is composition?
Composition is a strong OWNS-A relationship. The parent owns children. Children cannot exist without the parent. If the parent is destroyed, children are also destroyed. The parent controls the entire lifecycle: creation, modification, and destruction.
package com.bank.model;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
public class Account {
private String accountId;
private BigDecimal balance;
private final List<Transaction> transactions = new ArrayList<>(); // composition: owns
public void deposit(BigDecimal amount) {
balance = balance.add(amount);
transactions.add(new Transaction("CREDIT", amount, LocalDateTime.now()));
// Account CREATES the transaction. It owns it.
}
public void close() {
transactions.clear(); // transactions destroyed with account
// In JPA: @OneToMany(cascade = ALL, orphanRemoval = true)
}
}
// Transaction cannot exist without an Account.
How do association, aggregation, and composition compare?
| Aspect | Association | Aggregation | Composition | |--------|------------|-------------|-------------| | Relationship | Uses-A | Has-A (weak) | Owns-A (strong) | | Lifecycle | Independent | Independent | Bound to parent | | Child survives parent? | Yes | Yes | No | | Who creates child? | External | External | Parent | | UML notation | Arrow (-->) | Hollow diamond | Filled diamond | | JPA cascade | None | None | cascade ALL + orphanRemoval | | Example | Service uses Provider | Branch has Traders | Account owns Transactions |
Why is OOP important?
OOP provides three core benefits that make large-scale software manageable.
// 1. MODULARITY: each class is a self-contained unit
// AccountService: handles balance, deposits, withdrawals
// TradeService: handles trade execution
// NotificationService: handles SMS/email
// Each can be developed, tested, and deployed independently.
// 2. MAINTAINABILITY: change one class without breaking others
// Change NotificationService from SMS to email: TradeService unchanged.
// Add NRIAccount: InterestBatchService unchanged (polymorphism).
// 3. REAL-WORLD MODELING: objects map to real things
// Account object = real bank account at National Bank of India
// Trade object = real stock trade on NSE
// Customer object = real customer like Rajesh
How do all seven concepts appear in one banking system?
// ENCAPSULATION: Account.balance is private
// ABSTRACTION: PaymentService.transfer() hides NEFT/UPI complexity
// INHERITANCE: SavingsAccount extends Account
// POLYMORPHISM: account.calculateInterest() dispatches to correct override
// ASSOCIATION: SettlementService uses ClearingHouse (injected)
// AGGREGATION: TradingDepartment has Traders (traders survive dissolution)
// COMPOSITION: Trade owns Fees (fees die with the trade)
What are common mistakes when modeling relationships?
The most common mistake is confusing aggregation and composition. Ask: can the child exist meaningfully without the parent? If yes, it is aggregation. If no, it is composition.
// WRONG: treating composition as aggregation
// Loan-EMI is composition, not aggregation.
// An EMI without a Loan is meaningless.
// If you model it as aggregation (no cascade delete),
// closing a loan leaves orphan EMI rows in the database.
// CORRECT:
@OneToMany(mappedBy = "loan", cascade = CascadeType.ALL, orphanRemoval = true)
private List<EMI> emis; // composition: EMIs die with the loan
What should a senior engineer know?
- In Spring, association is the default relationship: services use other services via constructor injection.
- Domain-Driven Design maps aggregation and composition to Aggregate Roots: the root entity owns its children.
- Excessive inheritance hierarchies are a code smell. Prefer composition (HAS-A) over inheritance (IS-A) for code reuse.
- Modern Java (records, sealed classes) adds new tools: records enforce immutability (encapsulation), sealed classes control inheritance hierarchies.
Visual Overview
RELATIONSHIP STRENGTH ───────────────────────────────────────────── Weakest Strongest ───────────────────────────────────────────── Association Aggregation Composition (uses-a) (has-a weak) (owns-a strong) A ────→ B A ◇────→ B A ◆────→ B independent B survives A B dies with A ┌──────────────────────────────────────────┐ │ SEVEN OOP CONCEPTS IN BANKING │ ├──────────────────────────────────────────┤ │ PILLARS: │ │ Encapsulation → Account.balance private │ │ Abstraction → PaymentService.transfer │ │ Inheritance → SavingsAccount extends │ │ Polymorphism → calculateInterest() │ ├──────────────────────────────────────────┤ │ RELATIONSHIPS: │ │ Association → Service uses Provider │ │ Aggregation → Department has Traders │ │ Composition → Account owns Transactions│ └──────────────────────────────────────────┘
Key Takeaway
OOP has seven concepts: four pillars (encapsulation, abstraction, inheritance, polymorphism) and three relationship types (association, aggregation, composition). Association is the weakest: object A uses object B, both exist independently (SettlementService uses ClearingHouse). Aggregation is weak HAS-A: parent contains children but children survive if the parent is destroyed (TradingDepartment has Traders who move to another department when the desk is dissolved). Composition is strong OWNS-A: parent owns children, children are created by the parent and destroyed with it (Account owns Transactions that are deleted when the account is closed).
In Pankaj's banking architecture at National Bank of India, all seven concepts coexist in one system. SettlementService is associated with ClearingHouse through Spring dependency injection: replace the clearing house implementation and the settlement service continues unchanged. TradingDepartment aggregates Traders: dissolving the department returns the traders who can join a new department. Account composes Transactions: the deposit method creates transaction records that are permanently bound to the account and garbage collected when the account is closed. In JPA, composition maps to cascade ALL with orphanRemoval. Aggregation does not cascade deletes.
OOP matters because of three benefits: modularity (each class is a self-contained unit), maintainability (changing fee calculation requires zero changes to notification code), and real-world modeling (the code structure mirrors the banking domain).
Remember one sentence: four pillars build individual classes, three relationships connect them, and together they produce modular, maintainable software that mirrors the real world.
---