Dependency
Temporary use - weakest relationship between classes.
Dependency is the weakest relationship where one class uses another temporarily. The dependent class doesn’t store a reference to the other class - it only uses it as a parameter, local variable, or return type.
What is Dependency?
Section titled “What is Dependency?”Dependency represents:
- “Uses temporarily” relationship
- No ownership - doesn’t store reference
- Temporary use - only during method execution
- Weakest relationship - no coupling beyond method call
Key Characteristics
Section titled “Key Characteristics”- Temporary use - Only during method execution
- No storage - Not stored as instance variable
- Method parameters - Usually passed as parameters
- Dashed arrow in UML diagrams
Basic Dependency Example
Section titled “Basic Dependency Example” 💡 Tip: Click dropdown to switch between languages
class Order: def __init__(self, order_id: str): self.order_id = order_id self.total = 0
def calculate_total(self, calculator): """Dependency - uses Calculator temporarily""" # Calculator is passed in, not stored self.total = calculator.add(100, 50) return self.total
def print_receipt(self, printer): """Dependency - uses Printer temporarily""" printer.print(f"Order {self.order_id}: ${self.total}")
class Calculator: def add(self, a, b): return a + b
class Printer: def print(self, text): print(text)
order = Order("ORD-001")calculator = Calculator()printer = Printer()
order.calculate_total(calculator) # Uses calculatororder.print_receipt(printer) # Uses printer# calculator and printer are not stored in orderpublic class Order { private String orderId; private double total;
public Order(String orderId) { this.orderId = orderId; this.total = 0; }
// Dependency - uses Calculator temporarily public double calculateTotal(Calculator calculator) { // Calculator is passed in, not stored this.total = calculator.add(100, 50); return total; }
// Dependency - uses Printer temporarily public void printReceipt(Printer printer) { printer.print("Order " + orderId + ": $" + total); }}
public class Calculator { public double add(double a, double b) { return a + b; }}
public class Printer { public void print(String text) { System.out.println(text); }}
// Usagepublic class Main { public static void main(String[] args) { Order order = new Order("ORD-001"); Calculator calculator = new Calculator(); Printer printer = new Printer();
order.calculateTotal(calculator); // Uses calculator order.printReceipt(printer); // Uses printer // calculator and printer are not stored in order }}class Order { private orderId: string; private total: number;
constructor(orderId: string) { this.orderId = orderId; this.total = 0; }
// Dependency - uses Calculator temporarily calculateTotal(calculator: Calculator): number { // Calculator is passed in, not stored this.total = calculator.add(100, 50); return this.total; }
// Dependency - uses Printer temporarily printReceipt(printer: Printer): void { printer.print(`Order ${this.orderId}: $${this.total}`); }}
class Calculator { add(a: number, b: number): number { return a + b; }}
class Printer { print(text: string): void { console.log(text); }}
// Usageconst order = new Order("ORD-001");const calculator = new Calculator();const printer = new Printer();
order.calculateTotal(calculator); // Uses calculatororder.printReceipt(printer); // Uses printer// calculator and printer are not stored in order#include <iostream>#include <string>
class Calculator {public: double add(double a, double b) { return a + b; }};
class Printer {public: void print(const std::string& text) { std::cout << text << std::endl; }};
class Order {private: std::string orderId; double total;
public: Order(const std::string& orderId) : orderId(orderId), total(0) {}
// Dependency - uses Calculator temporarily double calculateTotal(Calculator& calculator) { // Calculator is passed in, not stored total = calculator.add(100, 50); return total; }
// Dependency - uses Printer temporarily void printReceipt(Printer& printer) { printer.print("Order " + orderId + ": $" + std::to_string(total)); }};
int main() { Order order("ORD-001"); Calculator calculator; Printer printer;
order.calculateTotal(calculator); // Uses calculator order.printReceipt(printer); // Uses printer // calculator and printer are not stored in order
return 0;}using System;
public class Order{ private string orderId; private double total;
public Order(string orderId) { this.orderId = orderId; this.total = 0; }
// Dependency - uses Calculator temporarily public double CalculateTotal(Calculator calculator) { // Calculator is passed in, not stored this.total = calculator.Add(100, 50); return total; }
// Dependency - uses Printer temporarily public void PrintReceipt(Printer printer) { printer.Print($"Order {orderId}: ${total}"); }}
public class Calculator{ public double Add(double a, double b) { return a + b; }}
public class Printer{ public void Print(string text) { Console.WriteLine(text); }}
class Program{ static void Main() { Order order = new Order("ORD-001"); Calculator calculator = new Calculator(); Printer printer = new Printer();
order.CalculateTotal(calculator); // Uses calculator order.PrintReceipt(printer); // Uses printer // calculator and printer are not stored in order }}package main
import "fmt"
type Order struct { orderID string total float64}
func NewOrder(orderID string) *Order { return &Order{orderID: orderID}}
func (o *Order) CalculateTotal(calc *Calculator) float64 { o.total = calc.Add(100, 50) return o.total}
func (o *Order) PrintReceipt(pr *Printer) { pr.Print(fmt.Sprintf("Order %s: $%.0f", o.orderID, o.total))}
type Calculator struct{}
func (*Calculator) Add(a, b float64) float64 { return a + b}
type Printer struct{}
func (*Printer) Print(text string) { fmt.Println(text)}
func main() { order := NewOrder("ORD-001") calculator := &Calculator{} printer := &Printer{} order.CalculateTotal(calculator) order.PrintReceipt(printer)}struct Order { order_id: String, total: f64,}
impl Order { fn new(order_id: impl Into<String>) -> Self { Self { order_id: order_id.into(), total: 0.0, } }
fn calculate_total(&mut self, calculator: &Calculator) -> f64 { self.total = calculator.add(100.0, 50.0); self.total }
fn print_receipt(&self, printer: &Printer) { printer.print(&format!("Order {}: ${:.0}", self.order_id, self.total)); }}
struct Calculator;
impl Calculator { fn add(&self, a: f64, b: f64) -> f64 { a + b }}
struct Printer;
impl Printer { fn print(&self, text: &str) { println!("{}", text); }}
fn main() { let mut order = Order::new("ORD-001"); let calculator = Calculator; let printer = Printer;
order.calculate_total(&calculator); order.print_receipt(&printer); // calculator and printer are not stored in order}Visual Representation
Section titled “Visual Representation”Real-World Example: Payment Processing
Section titled “Real-World Example: Payment Processing” 💡 Tip: Click dropdown to switch between languages
class ShoppingCart: def __init__(self): self.items = [] self.total = 0.0
def add_item(self, item: str, price: float): self.items.append((item, price)) self.total += price
def checkout(self, payment_processor, validator): """Dependency - uses PaymentProcessor and Validator temporarily""" # Validator is used temporarily if not validator.validate(self.total): return "Invalid amount"
# PaymentProcessor is used temporarily result = payment_processor.process(self.total) return result
class PaymentProcessor: def process(self, amount: float): return f"Processing payment of ${amount:.2f}"
class Validator: def validate(self, amount: float): return amount > 0
cart = ShoppingCart()cart.add_item("Laptop", 999.99)
processor = PaymentProcessor()validator = Validator()
print(cart.checkout(processor, validator)) # Uses both temporarilypublic class ShoppingCart { private java.util.List<String> items; private double total;
public ShoppingCart() { this.items = new java.util.ArrayList<>(); this.total = 0.0; }
public void addItem(String item, double price) { items.add(item); total += price; }
// Dependency - uses PaymentProcessor and Validator temporarily public String checkout(PaymentProcessor processor, Validator validator) { // Validator is used temporarily if (!validator.validate(total)) { return "Invalid amount"; }
// PaymentProcessor is used temporarily return processor.process(total); }}
public class PaymentProcessor { public String process(double amount) { return String.format("Processing payment of $%.2f", amount); }}
public class Validator { public boolean validate(double amount) { return amount > 0; }}
// Usagepublic class Main { public static void main(String[] args) { ShoppingCart cart = new ShoppingCart(); cart.addItem("Laptop", 999.99);
PaymentProcessor processor = new PaymentProcessor(); Validator validator = new Validator();
System.out.println(cart.checkout(processor, validator)); // Uses both temporarily }}class ShoppingCart { private items: Array<[string, number]>; private total: number;
constructor() { this.items = []; this.total = 0.0; }
addItem(item: string, price: number): void { this.items.push([item, price]); this.total += price; }
// Dependency - uses PaymentProcessor and Validator temporarily checkout(processor: PaymentProcessor, validator: Validator): string { // Validator is used temporarily if (!validator.validate(this.total)) { return "Invalid amount"; }
// PaymentProcessor is used temporarily return processor.process(this.total); }}
class PaymentProcessor { process(amount: number): string { return `Processing payment of $${amount.toFixed(2)}`; }}
class Validator { validate(amount: number): boolean { return amount > 0; }}
// Usageconst cart = new ShoppingCart();cart.addItem("Laptop", 999.99);
const processor = new PaymentProcessor();const validator = new Validator();
console.log(cart.checkout(processor, validator)); // Uses both temporarily#include <iostream>#include <string>#include <vector>#include <iomanip>#include <sstream>
class Validator {public: bool validate(double amount) { return amount > 0; }};
class PaymentProcessor {public: std::string process(double amount) { std::ostringstream oss; oss << std::fixed << std::setprecision(2); oss << "Processing payment of $" << amount; return oss.str(); }};
class ShoppingCart {private: std::vector<std::pair<std::string, double>> items; double total;
public: ShoppingCart() : total(0.0) {}
void addItem(const std::string& item, double price) { items.push_back({item, price}); total += price; }
// Dependency - uses PaymentProcessor and Validator temporarily std::string checkout(PaymentProcessor& processor, Validator& validator) { // Validator is used temporarily if (!validator.validate(total)) { return "Invalid amount"; }
// PaymentProcessor is used temporarily return processor.process(total); }};
int main() { ShoppingCart cart; cart.addItem("Laptop", 999.99);
PaymentProcessor processor; Validator validator;
std::cout << cart.checkout(processor, validator) << std::endl; // Uses both temporarily
return 0;}using System;using System.Collections.Generic;
public class ShoppingCart{ private List<(string item, double price)> items; private double total;
public ShoppingCart() { this.items = new List<(string, double)>(); this.total = 0.0; }
public void AddItem(string item, double price) { items.Add((item, price)); total += price; }
// Dependency - uses PaymentProcessor and Validator temporarily public string Checkout(PaymentProcessor processor, Validator validator) { // Validator is used temporarily if (!validator.Validate(total)) { return "Invalid amount"; }
// PaymentProcessor is used temporarily return processor.Process(total); }}
public class PaymentProcessor{ public string Process(double amount) { return $"Processing payment of ${amount:F2}"; }}
public class Validator{ public bool Validate(double amount) { return amount > 0; }}
class Program{ static void Main() { ShoppingCart cart = new ShoppingCart(); cart.AddItem("Laptop", 999.99);
PaymentProcessor processor = new PaymentProcessor(); Validator validator = new Validator();
Console.WriteLine(cart.Checkout(processor, validator)); // Uses both temporarily }}package main
import ( "fmt")
type ShoppingCart struct { items []struct { item string price float64 } total float64}
func NewShoppingCart() *ShoppingCart { return &ShoppingCart{}}
func (c *ShoppingCart) AddItem(item string, price float64) { c.items = append(c.items, struct { item string price float64 }{item: item, price: price}) c.total += price}
func (c *ShoppingCart) Checkout(processor *PaymentProcessor, validator *Validator) string { if !validator.Validate(c.total) { return "Invalid amount" } return processor.Process(c.total)}
type PaymentProcessor struct{}
func (*PaymentProcessor) Process(amount float64) string { return fmt.Sprintf("Processing payment of $%.2f", amount)}
type Validator struct{}
func (*Validator) Validate(amount float64) bool { return amount > 0}
func main() { cart := NewShoppingCart() cart.AddItem("Laptop", 999.99) processor := &PaymentProcessor{} validator := &Validator{} fmt.Println(cart.Checkout(processor, validator))}struct ShoppingCart { items: Vec<(String, f64)>, total: f64,}
impl ShoppingCart { fn new() -> Self { Self { items: Vec::new(), total: 0.0, } }
fn add_item(&mut self, item: impl Into<String>, price: f64) { self.items.push((item.into(), price)); self.total += price; }
fn checkout(&self, processor: &PaymentProcessor, validator: &Validator) -> String { if !validator.validate(self.total) { return "Invalid amount".to_string(); } processor.process(self.total) }}
struct PaymentProcessor;
impl PaymentProcessor { fn process(&self, amount: f64) -> String { format!("Processing payment of ${:.2}", amount) }}
struct Validator;
impl Validator { fn validate(&self, amount: f64) -> bool { amount > 0.0 }}
fn main() { let mut cart = ShoppingCart::new(); cart.add_item("Laptop", 999.99);
let processor = PaymentProcessor; let validator = Validator;
println!("{}", cart.checkout(&processor, &validator));}Dependency vs Association
Section titled “Dependency vs Association”| Feature | Dependency | Association |
|---|---|---|
| Duration | Temporary | Persistent |
| Storage | Not stored | Stored as reference |
| Lifecycle | No coupling | Some coupling |
| UML Symbol | Dashed arrow | Solid arrow |
| Example | Order uses Calculator | Teacher has Courses |
Key Takeaways
Section titled “Key Takeaways”When to Use Dependency
Section titled “When to Use Dependency”Use Dependency when:
- Class uses another temporarily
- Passing objects as method parameters
- Using objects as local variables
- You want minimal coupling
- Relationship is not persistent
- Objects are created externally
Examples:
- Order uses Calculator (for calculation)
- Order uses Printer (to print receipt)
- ShoppingCart uses PaymentProcessor (to process payment)
- Report uses Formatter (to format output)
- Service uses Logger (to log messages)