Example Of A Uml Class Diagram

7 min read

A UML class diagram serves as the blueprint for object-oriented software systems, offering a static view of the application’s structure by modeling classes, their attributes, operations, and the relationships between them. Whether you are designing a new enterprise application, refactoring legacy code, or documenting an existing architecture for a development team, mastering this diagram type is essential for clear technical communication. This guide walks through a comprehensive, real-world scenario to illustrate how these components fit together, moving beyond abstract shapes into practical design decisions.

Understanding the Core Building Blocks

Before diving into a complex example, it is vital to recognize the standard notation. A class is represented by a rectangle divided into three horizontal compartments. Also, the top compartment holds the class name (bold, centered, capitalized). Because of that, the middle compartment lists attributes (fields or properties), formatted as visibility name: type [multiplicity] = default_value. The bottom compartment details operations (methods), shown as visibility name(parameter_list): return_type Worth keeping that in mind..

This is where a lot of people lose the thread Worth keeping that in mind..

Visibility markers are critical for encapsulation:

  • + Public: Accessible from anywhere. Here's the thing — * - Private: Accessible only within the class. * # Protected: Accessible within the class and subclasses.
  • ~ Package: Accessible within the same package.

Relationships act as the connective tissue. Association represents a general binary relationship (e.So g. , "A Student enrolls in a Course"). Aggregation ("has-a") implies a whole-part relationship where the part can exist independently (e.Think about it: g. , a Department and a Professor). Composition ("owns-a") is a stronger form where the part’s lifecycle depends on the whole (e.So naturally, g. Now, , a House and its Rooms). So Inheritance (Generalization) represents an "is-a" relationship (e. g., a SavingsAccount is a BankAccount). Dependency indicates a weaker, often temporary relationship, such as a method parameter or local variable usage. Realization connects an interface to the class that implements it Worth keeping that in mind..

Case Study: Designing an E-Commerce Order Management System

To demonstrate these concepts cohesively, let us model the core domain of an e-commerce platform focused on Order Management. This domain is rich enough to showcase inheritance, composition, interfaces, and complex multiplicities without becoming unreadable.

1. The Actor and Profile Hierarchy (Inheritance & Abstraction)

Every system needs users. Instead of a single monolithic User class, we use inheritance to differentiate behaviors.

Abstract Class: UserAccount

  • Attributes: - userId: UUID, - email: String, - passwordHash: String, - createdAt: DateTime, - isActive: Boolean
  • Operations: + authenticate(credentials): Boolean, + updateProfile(data): void, + deactivate(): void

Subclass: Customer (extends UserAccount)

  • Attributes: - loyaltyTier: Enum {BRONZE, SILVER, GOLD}, - shippingAddresses: List<Address>
  • Operations: + placeOrder(cart): Order, + viewOrderHistory(): List<Order>, + addAddress(addr): void

Subclass: AdminUser (extends UserAccount)

  • Attributes: - permissions: Set<String>, - lastLoginIp: String
  • Operations: + manageInventory(product): void, + viewSalesReport(): Report, + banUser(userId): void

Design Note: Making UserAccount abstract (italicized name in UML) prevents direct instantiation, forcing the system to create either a Customer or AdminUser. This enforces the Liskov Substitution Principle—any code expecting a UserAccount can safely handle a Customer or AdminUser.

2. The Product Catalog (Interfaces & Composition)

Products vary wildly (physical goods, digital downloads, subscriptions). An interface defines the contract, while concrete classes handle specifics.

Interface: IPurchasable

  • Operations: + getPrice(): Money, + getTaxRate(): Float, + isInStock(): Boolean

Class: PhysicalProduct (implements IPurchasable)

  • Attributes: - sku: String, - weight: Float, - dimensions: Dimension, - stockQuantity: Integer
  • Operations: + calculateShippingCost(destination): Money, + reserveStock(qty): Boolean

Class: DigitalProduct (implements IPurchasable)

  • Attributes: - downloadLink: URL, - fileSize: Long, - licenseKey: String
  • Operations: + generateLicenseKey(): String, + invalidateLink(): void

Class: ProductBundle (Composition) A bundle contains other products. If the bundle is deleted, the specific bundle-items (the mapping entries) are deleted, though the underlying PhysicalProduct or DigitalProduct entities remain in the catalog Most people skip this — try not to..

  • Attributes: - bundleId: UUID, - discountPercent: Float
  • Composition: ProductBundle composes BundleItem (Multiplicity: 1..* on BundleItem side).
  • Class BundleItem: - quantity: Integer, - linkedProduct: IPurchasable (Association to interface).

3. The Order Aggregate (Composition & State Management)

The Order is the transactional heart. It owns OrderLineItems and a ShippingInfo object. This is a textbook example of Composition: an OrderLineItem has no meaning without its parent Order, and ShippingInfo is specific to this single transaction.

Class: Order

  • Attributes: - orderId: UUID, - orderDate: DateTime, - status: Enum {PENDING, PAID, SHIPPED, DELIVERED, CANCELLED, REFUNDED}, - subtotal: Money, - taxTotal: Money, - shippingCost: Money
  • Operations: + addItem(product, qty): void, + removeItem(lineItemId): void, + calculateTotals(): void, + processPayment(paymentDetails): PaymentResult, + markAsShipped(trackingNum): void

Class: OrderLineItem (Composed by Order)

  • Attributes: - lineItemId: UUID, - quantity: Integer, - unitPrice: Money (Snapshot of price at time of purchase), - lineTotal: Money
  • Association: * OrderLineItem -- 1 IPurchasable (The item references the product purchased).

Class: ShippingInfo (Composed by Order)

  • Attributes: - recipientName: String, - street: String, - city: String, - postalCode: String, - country: String, - phoneNumber: String
  • Operations: + formatLabel(): String

Class: PaymentTransaction (Association) An Order has PaymentTransactions (plural, to handle partial refunds or split payments), but a Transaction exists as a distinct financial record Practical, not theoretical..

  • Attributes: - transactionId: UUID, - amount: Money, - gateway: String (e.g., Stripe, PayPal), - gatewayRef: String, - status: Enum {AUTHORIZED, CAPTURED, FAILED, REFUNDED}
  • Operations: + refund(amount): RefundResult

4. Inventory and Warehouse Logic (Aggregation & Qualified Association)

Inventory management introduces Aggregation. A Warehouse has InventoryItem instances, but an InventoryItem (representing a specific SKU in a specific location) could theoretically be moved to another warehouse, meaning it doesn't die with the warehouse.

Class: Warehouse

  • Attributes: - warehouseId: UUID, - name: String, `- address:
  • address: String (full postal address of the facility)
  • capacity: Integer (maximum number of distinct SKUs the warehouse can hold)
  • currentUtilization: Integer (running count of occupied slots, updated automatically by inventory movements)

Operations:
+ receiveInventory(item: InventoryItem, qty: Integer): void – adds quantity to an existing slot or creates a new one if the SKU is not present.
+ pickInventory(item: InventoryItem, qty: Integer): Boolean – attempts to reserve the requested quantity; returns false when insufficient stock exists.
+ transferTo(otherWarehouse: Warehouse, item: InventoryItem, qty: Integer): Boolean – moves stock between warehouses, decrementing the source and incrementing the target if both operations succeed.
+ getUtilizationPercentage(): Float – returns currentUtilization / capacity * 100 Nothing fancy..


Class InventoryItem (Aggregated by Warehouse)

An InventoryItem represents a concrete stock keeping unit (SKU) residing in a particular warehouse. Its lifecycle is independent of any single Warehouse; it can be relocated, split, or written off without destroying the underlying product definition.

  • Attributes:

    • inventoryItemId: UUID
    • linkedProduct: IPurchasable (Association to the product catalog; unchanged when the item moves)
    • quantityOnHand: Integer
    • reservedQuantity: Integer (units allocated to pending orders but not yet shipped)
    • reorderThreshold: Integer (triggers replenishment alerts)
    • maxStockLevel: Integer (upper bound for automatic restocking)
  • Operations:

    • availableQuantity(): Integer – returns quantityOnHand - reservedQuantity.
    • reserve(qty: Integer): Boolean – attempts to increase reservedQuantity; fails if availableQuantity() < qty.
    • releaseReservation(qty: Integer): void – decreases reservedQuantity (e.g., when an order is cancelled).
    • adjustStock(delta: Integer): void – safely updates quantityOnHand (positive for receipts, negative for damages/returns) and triggers threshold checks.

Because a Warehouse aggregates InventoryItem instances, removing a warehouse does not automatically delete its items; instead, a domain service (e.g., InventoryReallocationService) would either relocate the items to another warehouse or mark them for disposal, preserving the integrity of the product catalog.


Qualified Association: Warehouse ↔ InventoryItem

To model the fast lookup of a specific SKU within a warehouse, we employ a qualified association. Think about it: the qualifier is the product’s SKU (or linkedProduct. productId).

Warehouse "1" ----< "0..*" InventoryItem : skuQualifier

This notation conveys that, given a warehouse and a SKU, at most one InventoryItem instance exists. The qualifier enables O(1) retrieval in implementation (e.g., a Map<SKU, InventoryItem> inside each Warehouse).


5. Cross‑Cutting Concerns & Domain Services

While aggregates encapsulate core business invariants, certain operations span multiple aggregates and are best expressed as domain services:

  • PricingService – calculates the final price of a BundleItem or OrderLineItem by applying active promotions, tiered discounts, and tax rules. It reads from the Promotion aggregate (which itself composes PromotionRule objects) but does not own any state.
  • InventoryAllocationService – coordinates Order creation with Warehouse inventory: for each OrderLineItem, it selects the optimal warehouse (based on proximity, stock level, and shipping cost), calls Warehouse.pickInventory, and reserves the quantity. If any line cannot be fulfilled, the service rolls back prior reservations and returns an allocation failure to the caller.
Hot Off the Press

New and Noteworthy

Round It Out

Keep the Momentum

Thank you for reading about Example Of A Uml Class Diagram. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home