How do objects collaborate in a well-designed Java system, and how do you keep that collaboration from turning into a tangle?
Collaboration in an object-oriented system happens through messages. One object holds a reference to another and calls a method on it, and each object is responsible only for its own state. The system becomes a network of objects that each know a little about a few others.
public class Main {
public static void main(String[] args) {
Cart cart = new Cart();
cart.add(new Book("Effective Java", 45.0));
cart.add(new Book("Clean Code", 38.5));
cart.checkout(new CashPayment());
System.out.println("total = " + cart.total());
}
}
class Cart {
private final java.util.List<Book> items = new java.util.ArrayList<>();
void add(Book b) { items.add(b); }
double total() {
double sum = 0;
for (Book b : items) { sum += b.price(); }
return sum;
}
void checkout(Payment payment) { payment.pay(total()); }
}
class Book {
private final String title;
private final double price;
Book(String title, double price) { this.title = title; this.price = price; }
double price() { return price; }
}
interface Payment {
void pay(double amount);
}
class CashPayment implements Payment {
public void pay(double amount) { System.out.println("paid " + amount); }
}The example shows the three roles. The cart owns the books and knows how to total them. The payment is a collaborator the cart uses for one operation, and it arrives from outside through the method argument. The cart does not know which payment it will use, so a different one can be passed in with no change to the cart. The output shows the checkout happening and the total being reported separately.
The design rule that keeps this manageable is that every collaborator should have one job. The cart knows about books and about the payment contract, and it delegates. It does not know how to format money, how to persist an order or how to send a receipt, because those belong to other objects.
The way this goes wrong is when objects start reaching into each other. If the cart reached into the payment's fields, or if the order service called methods on the book's internals, the network would become a mesh where every object knows about every other. The defences are small collaborating objects, narrow interfaces, and passing collaborators in rather than constructing them inside.